From 0d2246ce15b81a9d2d10b63befb860ab205f7ff9 Mon Sep 17 00:00:00 2001 From: LAKHAN BAHETI Date: Wed, 10 Jan 2024 20:17:06 +0530 Subject: [PATCH 1/7] fix: issues filtering flow --- android/app/build.gradle | 2 +- lib/bottom_sheets/views_sheet.dart | 13 +- lib/config/apis.dart | 6 +- lib/provider/cycles_provider.dart | 74 ++-- lib/provider/issues_provider.dart | 356 ++++-------------- lib/provider/projects_provider.dart | 2 +- .../My_issues/my_issues_screen.dart | 13 +- .../Notification/notification.dart | 1 + .../ProjectDetail/CyclesTab/cycle_detail.dart | 19 +- .../ProjectDetail/project_detail.dart | 14 +- .../MainScreens/Projects/project_screen.dart | 14 +- .../on_boarding/auth/setup_workspace.dart | 24 +- lib/utils/bottom_sheet.helper.dart | 30 ++ lib/utils/extensions/list_extensions.dart | 6 + lib/utils/issues_filter/group_by_issues.dart | 143 +++++++ .../issues_filter/issue_filter.helper.dart | 43 +++ lib/utils/issues_filter/order_by_issues.dart | 101 +++++ 17 files changed, 478 insertions(+), 383 deletions(-) create mode 100644 lib/utils/bottom_sheet.helper.dart create mode 100644 lib/utils/issues_filter/group_by_issues.dart create mode 100644 lib/utils/issues_filter/issue_filter.helper.dart create mode 100644 lib/utils/issues_filter/order_by_issues.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 7d5d91dd..2b353645 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -53,7 +53,7 @@ android { applicationId "com.plane.so" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/lib/bottom_sheets/views_sheet.dart b/lib/bottom_sheets/views_sheet.dart index 6eeae719..1549907d 100644 --- a/lib/bottom_sheets/views_sheet.dart +++ b/lib/bottom_sheets/views_sheet.dart @@ -999,18 +999,7 @@ class _ViewsSheetState extends ConsumerState { .currentProject["id"], ); } else { - issueProvider.filterIssues( - fromViews: widget.fromView, - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: ref - .read(ProviderList.projectProvider) - .currentProject["id"], - issueCategory: IssueCategory.issues, - isArchived: widget.isArchived, - ); + issueProvider.applyIssueView(); } } diff --git a/lib/config/apis.dart b/lib/config/apis.dart index 71cc659b..73b0e32c 100644 --- a/lib/config/apis.dart +++ b/lib/config/apis.dart @@ -35,7 +35,7 @@ class APIs { static String states = '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/states/'; static String orderByGroupByTypeIssues = - '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/issues/?order_by=\$ORDERBY&group_by=\$GROUPBY&type=\$TYPE'; + '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/issues/?type=\$TYPE'; static String orderByGroupByTypeArchivedIssues = '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/archived-issues/?order_by=\$ORDERBY&group_by=\$GROUPBY&type=\$TYPE'; static String orderByGroupByIssues = @@ -66,8 +66,8 @@ class APIs { '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/issue-labels/'; static String projectViews = '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/project-views/'; - static String issueProperties = - '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/issue-properties/'; + static String issueDisplayProperties = + '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/issue-display-properties/'; static String issueDetails = '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/issues/\$ISSUEID/'; static String subIssues = diff --git a/lib/provider/cycles_provider.dart b/lib/provider/cycles_provider.dart index 8893aa36..f408a912 100644 --- a/lib/provider/cycles_provider.dart +++ b/lib/provider/cycles_provider.dart @@ -16,6 +16,7 @@ import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/global_functions.dart'; +import 'package:plane/utils/issues_filter/issue_filter.helper.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; @@ -51,12 +52,12 @@ class CyclesProvider with ChangeNotifier { List issuesResponse = []; List shrinkStates = []; Map filterIssues = {}; + List cycleIssuesList = []; Map issueProperty = {}; bool showEmptyStates = true; bool isIssuesEmpty = false; int cycleDetailSelectedIndex = 0; List queries = ['all', 'current', 'upcoming', 'completed', 'draft']; - List stateOrdering = []; List loadingCycleId = []; void setState() { notifyListeners(); @@ -385,14 +386,12 @@ class CyclesProvider with ChangeNotifier { // log(issues.groupBY.name); issues.issues = []; issuesResponse = []; - for (int j = 0; j < stateOrdering.length; j++) { + for (int j = 0; j < filterIssues.length; j++) { final List items = []; - - for (int i = 0; - filterIssues[stateOrdering[j]] != null && - i < filterIssues[stateOrdering[j]]!.length; - i++) { - issuesResponse.add(filterIssues[stateOrdering[j]]![i]); + final groupedIssues = filterIssues.values.toList()[j]; + final groupID = filterIssues.keys.elementAt(j); + for (int i = 0; i < groupedIssues.length; i++) { + issuesResponse.add(groupedIssues[i]); items.add( IssueCardWidget( from: PreviousScreen.cycles, @@ -409,7 +408,7 @@ class CyclesProvider with ChangeNotifier { bool userFound = false; for (int i = 0; i < issuesProvider.labels.length; i++) { - if (stateOrdering[j] == issuesProvider.labels[i]['id']) { + if (groupID == issuesProvider.labels[i]['id']) { label = issuesProvider.labels[i]; labelFound = true; break; @@ -417,7 +416,7 @@ class CyclesProvider with ChangeNotifier { } for (int i = 0; i < issuesProvider.members.length; i++) { - if (stateOrdering[j] == issuesProvider.members[i]['member']['id']) { + if (groupID == issuesProvider.members[i]['member']['id']) { userName = issuesProvider.members[i]['member']['first_name'] + ' ' + issuesProvider.members[i]['member']['last_name']; @@ -431,12 +430,12 @@ class CyclesProvider with ChangeNotifier { //log('RESPONSE : ' + filterIssues.toString()); // log('================================================================ ${stateOrdering[j]}'); var title = issues.groupBY == GroupBY.priority - ? stateOrdering[j] + ? groupID : issues.groupBY == GroupBY.state - ? issuesProvider.states[stateOrdering[j]]['name'] - : stateOrdering[j]; + ? issuesProvider.states[groupID]['name'] + : groupID; issues.issues.add(BoardListsData( - id: stateOrdering[j], + id: groupID, items: items, shrink: shrinkStates[j], index: j, @@ -455,7 +454,7 @@ class CyclesProvider with ChangeNotifier { : title = title[0].toString().toUpperCase() + title.toString().substring(1), header: Text( - stateOrdering[j], + groupID, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, @@ -633,11 +632,14 @@ class CyclesProvider with ChangeNotifier { notifyListeners(); return; } - (filterIssues[stateOrdering[newListIndex]] as List).insert(newCardIndex, - filterIssues[stateOrdering[oldListIndex]].removeAt(oldCardIndex)); + + final List newList = filterIssues.values.toList()[newListIndex]; + final List oldList = filterIssues.values.toList()[oldListIndex]; + + newList.insert(newCardIndex, oldList.removeAt(oldCardIndex)); notifyListeners(); - final issue = filterIssues[stateOrdering[newListIndex]][newCardIndex]; + final issue = newList[newCardIndex]; // log(issue.toString()); final response = await DioConfig().dioServe( hasAuth: true, @@ -655,19 +657,18 @@ class CyclesProvider with ChangeNotifier { httpMethod: HttpMethod.patch, data: issues.groupBY == GroupBY.state ? { - 'state': stateOrdering[newListIndex], + 'state': filterIssues.keys.elementAt(newListIndex), 'priority': issue['priority'] } : { 'state': issue['state'], - 'priority': stateOrdering[newListIndex], + 'priority': filterIssues.keys.elementAt(newListIndex) }); - filterIssues[stateOrdering[newListIndex]][newCardIndex] = response.data; + newList[newCardIndex] = response.data; final List labelDetails = []; final issuesProvider = ref!.read(ProviderList.issuesProvider); - filterIssues[stateOrdering[newListIndex]][newCardIndex]['labels'] - .forEach((element) { + newList[newCardIndex]['labels'].forEach((element) { for (int i = 0; i < issuesProvider.labels.length; i++) { if (issuesProvider.labels[i]['id'] == element) { labelDetails.add(issuesProvider.labels[i]); @@ -678,17 +679,16 @@ class CyclesProvider with ChangeNotifier { // labelDetails.add(labels.firstWhere((e) => e['id'] == element)); }); - filterIssues[stateOrdering[newListIndex]][newCardIndex]['label_details'] = - labelDetails; + newList[newCardIndex]['label_details'] = labelDetails; log(response.data.toString()); if (issues.groupBY == GroupBY.priority) { - log(filterIssues[stateOrdering[newListIndex]][newCardIndex]['name']); - filterIssues[stateOrdering[newListIndex]][newCardIndex]['priority'] = - stateOrdering[newListIndex]; + log(newList[newCardIndex]['name']); + newList[newCardIndex]['priority'] = + filterIssues.keys.elementAt(newListIndex); } if (issues.orderBY != OrderBY.manual) { - (filterIssues[stateOrdering[newListIndex]] as List).sort((a, b) { + newList.sort((a, b) { if (issues.orderBY == OrderBY.priority) { return priorityParser(a['priority']) .compareTo(priorityParser(b['priority'])); @@ -706,8 +706,8 @@ class CyclesProvider with ChangeNotifier { log("ISSUE REPOSITIONED"); notifyListeners(); } on DioException catch (err) { - (filterIssues[stateOrdering[oldListIndex]] as List).insert(oldCardIndex, - filterIssues[stateOrdering[newListIndex]].removeAt(newCardIndex)); + filterIssues.values.elementAt(oldListIndex).insert(oldCardIndex, + filterIssues.values.elementAt(newListIndex).removeAt(newCardIndex)); log(err.toString()); notifyListeners(); rethrow; @@ -802,6 +802,16 @@ class CyclesProvider with ChangeNotifier { } } + void applyCycleIssuesView() { + final issuesProvider = ref!.read(ProviderList.issuesProvider); + final labelIds = issuesProvider.labels.map((e) => e['id']).toList(); + filterIssues = IssueFilterHelper.organizeIssues( + cycleIssuesList, issues.groupBY, issues.orderBY, + labels: labelIds, + members: issuesProvider.members, + states: issuesProvider.states); + } + Future filterCycleIssues({ required String slug, required String projectId, @@ -841,10 +851,8 @@ class CyclesProvider with ChangeNotifier { shrinkStates.add(false); }); } else { - stateOrdering = []; shrinkStates = []; filterIssues.forEach((key, value) { - stateOrdering.add(key); shrinkStates.add(false); }); } diff --git a/lib/provider/issues_provider.dart b/lib/provider/issues_provider.dart index 88fd6b64..c36ef27a 100644 --- a/lib/provider/issues_provider.dart +++ b/lib/provider/issues_provider.dart @@ -13,6 +13,7 @@ import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/Creat import 'package:plane/utils/constants.dart'; import 'package:plane/utils/global_functions.dart'; import 'package:plane/utils/custom_toast.dart'; +import 'package:plane/utils/issues_filter/issue_filter.helper.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; import 'package:plane/config/apis.dart'; @@ -214,16 +215,12 @@ class IssuesProvider extends ChangeNotifier { int count = 0; issuesResponse = []; issues.issues = []; - for (int j = 0; j < stateOrdering.length; j++) { + for (int j = 0; j < groupByResponse.length; j++) { final List items = []; - if (groupByResponse[stateOrdering[j]] == null) { - continue; - } - for (int i = 0; - groupByResponse[stateOrdering[j]] != null && - i < groupByResponse[stateOrdering[j]]!.length; - i++) { - issuesResponse.add(groupByResponse[stateOrdering[j]]![i]); + final groupedIssues = groupByResponse.values.elementAt(j); + final groupID = groupByResponse.keys.elementAt(j); + for (int i = 0; i < groupedIssues.length; i++) { + issuesResponse.add(groupedIssues[i]); items.add( IssueCardWidget( @@ -242,7 +239,7 @@ class IssuesProvider extends ChangeNotifier { bool userFound = false; for (int i = 0; i < labels.length; i++) { - if (stateOrdering[j] == labels[i]['id']) { + if (groupID == labels[i]['id']) { label = labels[i]; labelFound = true; break; @@ -250,7 +247,7 @@ class IssuesProvider extends ChangeNotifier { } for (int i = 0; i < members.length; i++) { - if (stateOrdering[j] == members[i]['member']['id']) { + if (groupID == members[i]['member']['id']) { userName = members[i]['member']['first_name'] + ' ' + members[i]['member']['last_name']; @@ -268,12 +265,12 @@ class IssuesProvider extends ChangeNotifier { } String title = issues.groupBY == GroupBY.priority - ? stateOrdering[j] + ? groupID : issues.groupBY == GroupBY.state - ? states[stateOrdering[j]]['name'] - : stateOrdering[j]; + ? states[groupID]['name'] + : groupID; issues.issues.add(BoardListsData( - id: stateOrdering[j], + id: groupID, items: items, shrink: j >= shrinkStates.length ? false : shrinkStates[j], index: j, @@ -292,7 +289,7 @@ class IssuesProvider extends ChangeNotifier { : title = title[0].toString().toUpperCase() + title.toString().substring(1), header: Text( - stateOrdering[j], + groupID, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, @@ -462,7 +459,6 @@ class IssuesProvider extends ChangeNotifier { ), ); } - return issues.issues; } @@ -682,41 +678,40 @@ class IssuesProvider extends ChangeNotifier { hasBody: false, httpMethod: HttpMethod.get, ); - statesData = response.data; + // log(response.data.toString()); + statesData = {for (final value in response.data) value['id']: value}; states = {}; - for (int i = 0; i < response.data.length; i++) { - final String state = response.data.keys.elementAt(i); - for (int j = 0; j < response.data[state].length; j++) { - states[response.data[state][j]['id']] = response.data[state][j]; - stateIcons[response.data[state][j]['id']] = SvgPicture.asset( - state == 'backlog' - ? 'assets/svg_images/circle.svg' - : state == 'cancelled' - ? 'assets/svg_images/cancelled.svg' - : state == 'completed' - ? 'assets/svg_images/done.svg' - : state == 'started' - ? 'assets/svg_images/in_progress.svg' - : 'assets/svg_images/unstarted.svg', - height: 22, - width: 22, - colorFilter: int.tryParse( - "FF${response.data[state][j]['color'].toString().replaceAll('#', '')}", - radix: 16) != - null - ? ColorFilter.mode( - Color(int.parse( - "FF${response.data[state][j]['color'].toString().replaceAll('#', '')}", - radix: 16)), - BlendMode.srcIn) - : null); - - if (response.data[state][j]['default'] == true) { - defaultStatedetails[state] = { - 'name': response.data[state][j]['name'], - 'icon': stateIcons[response.data[state][j]['id']] - }; - } + for (int i = 0; i < statesData.length; i++) { + final String stateId = statesData.keys.elementAt(i); + states[stateId] = statesData[stateId]; + stateIcons[stateId] = SvgPicture.asset( + stateId == 'backlog' + ? 'assets/svg_images/circle.svg' + : stateId == 'cancelled' + ? 'assets/svg_images/cancelled.svg' + : stateId == 'completed' + ? 'assets/svg_images/done.svg' + : stateId == 'started' + ? 'assets/svg_images/in_progress.svg' + : 'assets/svg_images/unstarted.svg', + height: 22, + width: 22, + colorFilter: int.tryParse( + "FF${statesData[stateId]['color'].toString().replaceAll('#', '')}", + radix: 16) != + null + ? ColorFilter.mode( + Color(int.parse( + "FF${statesData[stateId]['color'].toString().replaceAll('#', '')}", + radix: 16)), + BlendMode.srcIn) + : null); + + if (statesData[stateId]['default'] == true) { + defaultStatedetails[stateId] = { + 'name': statesData[stateId]['name'], + 'icon': stateIcons[statesData[stateId]['id']] + }; } } stateOrdering = []; @@ -877,7 +872,6 @@ class IssuesProvider extends ChangeNotifier { } Future getIssues({required String slug, required String projID}) async { - // issueState = StateEnum.loading; try { final response = await DioConfig().dioServe( hasAuth: true, @@ -887,7 +881,6 @@ class IssuesProvider extends ChangeNotifier { hasBody: false, httpMethod: HttpMethod.get, ); - issuesResponse = response.data; issuesList = response.data; isISsuesEmpty = issuesResponse.isEmpty; @@ -963,14 +956,14 @@ class IssuesProvider extends ChangeNotifier { } } - Future getIssueProperties({required Enum issueCategory}) async { + Future getIssueDisplayProperties({required Enum issueCategory}) async { final cyclesProvider = ref!.read(ProviderList.cyclesProvider); final modulesProvider = ref!.read(ProviderList.modulesProvider); issueState = StateEnum.loading; try { var response = await DioConfig().dioServe( hasAuth: true, - url: APIs.issueProperties + url: APIs.issueDisplayProperties .replaceAll( "\$SLUG", ref! @@ -985,7 +978,7 @@ class IssuesProvider extends ChangeNotifier { if (response.data.isEmpty) { response = await DioConfig().dioServe( hasAuth: true, - url: APIs.issueProperties + url: APIs.issueDisplayProperties .replaceAll( "\$SLUG", ref! @@ -1072,11 +1065,6 @@ class IssuesProvider extends ChangeNotifier { cyclesProvider.issueProperty['properties']['estimate']; cyclesProvider.issues.displayProperties.startDate = cyclesProvider.issueProperty['properties']['start_date']; - cyclesProvider.issues.displayProperties.createdOn = - cyclesProvider.issueProperty['properties']?['created_on'] ?? - false; - cyclesProvider.issues.displayProperties.updatedOn = - cyclesProvider.issueProperty['properties']['updated_on']; ref!.read(ProviderList.cyclesProvider).issues.displayProperties = cyclesProvider.issues.displayProperties; } else if (issueCategory == IssueCategory.moduleIssues) { @@ -1156,13 +1144,11 @@ class IssuesProvider extends ChangeNotifier { }) async { final cyclesProvider = ref!.read(ProviderList.cyclesProvider); final modulesProvider = ref!.read(ProviderList.modulesProvider); - issuePropertyState = StateEnum.loading; - notifyListeners(); try { final response = await DioConfig().dioServe( hasAuth: true, url: - ("${APIs.issueProperties}${issueCategory == IssueCategory.cycleIssues ? cyclesProvider.issueProperty['id'] : issueCategory == IssueCategory.moduleIssues ? modulesProvider.issueProperty['id'] : issueProperty['id']}/") + ("${APIs.issueDisplayProperties}${issueCategory == IssueCategory.cycleIssues ? cyclesProvider.issueProperty['id'] : issueCategory == IssueCategory.moduleIssues ? modulesProvider.issueProperty['id'] : issueProperty['id']}/") .replaceAll( "\$SLUG", ref! @@ -1350,6 +1336,13 @@ class IssuesProvider extends ChangeNotifier { } } + void applyIssueView() { + final labelIds = labels.map((e) => e['id']).toList(); + groupByResponse = IssueFilterHelper.organizeIssues( + issuesList, issues.groupBY, issues.orderBY, + labels: labelIds, members: members, states: states); + } + Future filterIssues({ required String slug, required String projID, @@ -1359,27 +1352,9 @@ class IssuesProvider extends ChangeNotifier { String? moduleId, Enum issueCategory = IssueCategory.issues, }) async { - final cyclesProvider = ref!.read(ProviderList.cyclesProvider); - final modulesProvider = ref!.read(ProviderList.modulesProvider); - if (issueCategory == IssueCategory.issues) { - orderByState = StateEnum.loading; - notifyListeners(); - } - - // if(cycleIssues){ - // issues.groupBY = cyclesProvider.issues.groupBY; - // issues.orderBY = cyclesProvider.issues.orderBY; - // issues.issueType = cyclesProvider.issues.issueType; - // } - // else { - cyclesProvider.issues.groupBY = issues.groupBY; - cyclesProvider.issues.orderBY = issues.orderBY; - cyclesProvider.issues.issueType = issues.issueType; + orderByState = StateEnum.loading; + notifyListeners(); - modulesProvider.issues.groupBY = issues.groupBY; - modulesProvider.issues.orderBY = issues.orderBY; - modulesProvider.issues.issueType = issues.issueType; - // } if (issues.groupBY == GroupBY.labels) { getLabels(slug: slug, projID: projID); } else if (issues.groupBY == GroupBY.createdBY) { @@ -1400,111 +1375,14 @@ class IssuesProvider extends ChangeNotifier { tempIssueType = issues.issueType; tempProjectView = issues.projectView; } - if (issues.issueType != IssueType.all) { - url = (issueCategory == IssueCategory.cycleIssues - ? APIs.orderByGroupByCycleIssues - : issueCategory == IssueCategory.moduleIssues - ? APIs.orderByGroupByModuleIssues - : isArchived - ? APIs.orderByGroupByTypeArchivedIssues - : APIs.orderByGroupByTypeIssues) - .replaceAll("\$SLUG", slug) - .replaceAll('\$PROJECTID', projID) - .replaceAll( - '\$CYCLEID', cycleId ?? cyclesProvider.currentCycle['id'] ?? '') - .replaceAll('\$MODULEID', - moduleId ?? modulesProvider.currentModule['id'] ?? '') - .replaceAll('\$ORDERBY', Issues.fromOrderBY(issues.orderBY)) - .replaceAll('\$GROUPBY', Issues.fromGroupBY(issues.groupBY)) - .replaceAll('\$TYPE', Issues.fromIssueType(issues.issueType)); - if (issues.filters.priorities.isNotEmpty) { - url = - '$url&priority=${issues.filters.priorities.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } - if (issues.filters.states.isNotEmpty) { - url = - '$url&state=${issues.filters.states.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - // print(url); - } - if (issues.filters.assignees.isNotEmpty) { - url = - '$url&assignees=${issues.filters.assignees.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - // print(url); - } - if (issues.filters.createdBy.isNotEmpty) { - url = - '$url&created_by=${issues.filters.createdBy.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } - if (issues.filters.labels.isNotEmpty) { - url = - '$url&labels=${issues.filters.labels.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - // print(url); - } - if (issues.filters.targetDate.isNotEmpty) { - url = - '$url&target_date=${issues.filters.targetDate.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } - if (issues.filters.startDate.isNotEmpty) { - url = - '$url&start_date=${issues.filters.startDate.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } else { - url = url; - } - } else { - url = (issueCategory == IssueCategory.cycleIssues - ? APIs.orderByGroupByCycleIssues - : issueCategory == IssueCategory.moduleIssues - ? APIs.orderByGroupByModuleIssues - : isArchived - ? APIs.orderByGroupByTypeArchivedIssues - : APIs.orderByGroupByTypeIssues) - .replaceAll("\$SLUG", slug) - .replaceAll('\$PROJECTID', projID) - .replaceAll( - '\$CYCLEID', cycleId ?? cyclesProvider.currentCycle['id'] ?? '') - .replaceAll('\$MODULEID', - moduleId ?? modulesProvider.currentModule['id'] ?? '') - .replaceAll('\$ORDERBY', Issues.fromOrderBY(issues.orderBY)) - .replaceAll('\$GROUPBY', Issues.fromGroupBY(issues.groupBY)) - .replaceAll('\$TYPE', Issues.fromIssueType(issues.issueType)); - if (issues.filters.priorities.isNotEmpty) { - url = - '$url&priority=${issues.filters.priorities.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } - if (issues.filters.states.isNotEmpty) { - url = - '$url&state=${issues.filters.states.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } - if (issues.filters.assignees.isNotEmpty) { - url = - '$url&assignees=${issues.filters.assignees.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } - if (issues.filters.createdBy.isNotEmpty) { - url = - '$url&created_by=${issues.filters.createdBy.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } - if (issues.filters.labels.isNotEmpty) { - url = - '$url&labels=${issues.filters.labels.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } - if (issues.filters.targetDate.isNotEmpty) { - url = - '$url&target_date=${issues.filters.targetDate.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } - if (issues.filters.startDate.isNotEmpty) { - url = - '$url&start_date=${issues.filters.startDate.toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', '')}'; - } else { - url = url; - } - } - url = '$url&sub_issue=${issues.showSubIssues}'; - if (issues.groupBY == GroupBY.none) { - url = url.replaceAll('&group_by=none', ''); - stateOrdering = ['All Issues']; - } - dynamic temp; + url = APIs.orderByGroupByTypeIssues + .replaceAll("\$SLUG", slug) + .replaceAll('\$PROJECTID', projID) + .replaceAll('\$TYPE', Issues.fromIssueType(issues.issueType)); + url = '$url${IssueFilterHelper.getFilterQueryParams(issues.filters)}'; + url = '$url&sub_issue=${issues.showSubIssues}'; + log('URL: $url'); try { final response = await DioConfig().dioServe( hasAuth: true, @@ -1512,102 +1390,18 @@ class IssuesProvider extends ChangeNotifier { hasBody: false, httpMethod: HttpMethod.get, ); - if (issueCategory == IssueCategory.cycleIssues) { - issuesList = []; - - if (issues.groupBY != GroupBY.none) { - temp = response.data; - for (final key in response.data.keys) { - issuesList.addAll(response.data[key]); - } - } else { - temp = {'All Issues': response.data}; - } - } else if (issueCategory == IssueCategory.moduleIssues) { - issuesList = []; - if (issues.groupBY != GroupBY.none) { - temp = response.data; - for (final key in response.data.keys) { - issuesList.addAll(response.data[key]); - } - } else { - temp = {'All Issues': response.data}; - } - } - - if (issueCategory == IssueCategory.issues) { - issuesResponse = []; - isISsuesEmpty = true; - shrinkStates = []; - issuesList = []; - if (issues.groupBY == GroupBY.none) { - if (response.data.isNotEmpty) { - isISsuesEmpty = false; - } - issuesList = response.data; - } else { - for (final key in response.data.keys) { - if (response.data[key].isNotEmpty) { - isISsuesEmpty = false; - } - issuesList.addAll(response.data[key]); - } - } - } - - // if(issueCategory == IssueCategory.archivedIssues){ - // archivedIssueResponse = []; - // isArchivedIssuesEmpty = true; - // archivedIssuesList = []; - - // for (final key in response.data.keys) { - // // log("KEY=$key"); - // if (response.data[key].isNotEmpty) { - // isArchivedIssuesEmpty = false; - // } - - // archivedIssuesList.addAll(response.data[key]); - // } - - // } + issuesList = response.data.values.toList(); + final organizedIssues = IssueFilterHelper.organizeIssues( + issuesList, issues.groupBY, issues.orderBY, + labels: labels.map((e) => e['id']).toList(), + members: members, + states: states); - //log("shrink states=${shrinkStates.toString()}"); if (issueCategory == IssueCategory.issues) { - if (issues.groupBY == GroupBY.state) { - groupByResponse = {}; - - if (issues.filters.states.isNotEmpty) { - for (final element in issues.filters.states) { - if (response.data[element] == null) { - groupByResponse[element] = []; - } else { - groupByResponse[element] = response.data[element]; - } - } - } else { - for (final element in stateOrdering) { - groupByResponse[element] = response.data[element] ?? []; - } - } - shrinkStates = List.generate(stateOrdering.length, (index) => false); - } else if (issues.groupBY == GroupBY.none) { - stateOrdering = ['All Issues']; - groupByResponse['All Issues'] = response.data; - } else { - stateOrdering = []; - response.data.forEach((key, value) { - stateOrdering.add(key); - }); - groupByResponse = response.data; - shrinkStates = List.generate(stateOrdering.length, (index) => false); - } - } - - if (issueCategory == IssueCategory.cycleIssues || + groupByResponse = organizedIssues; + } else if (issueCategory == IssueCategory.cycleIssues || issueCategory == IssueCategory.moduleIssues) { - cyclesProvider.stateOrdering = stateOrdering; - modulesProvider.stateOrdering = stateOrdering; - return temp; + return organizedIssues; } orderByState = StateEnum.success; notifyListeners(); diff --git a/lib/provider/projects_provider.dart b/lib/provider/projects_provider.dart index dccaf289..b3aba942 100644 --- a/lib/provider/projects_provider.dart +++ b/lib/provider/projects_provider.dart @@ -110,7 +110,7 @@ class ProjectsProvider extends ChangeNotifier { slug: workspaceSlug, projID: currentProject['id'], ); - prov.getIssueProperties(issueCategory: IssueCategory.issues); + prov.getIssueDisplayProperties(issueCategory: IssueCategory.issues); prov.getProjectView().then((value) { if (filters != null) { prov.issues.filters = filters; diff --git a/lib/screens/MainScreens/My_issues/my_issues_screen.dart b/lib/screens/MainScreens/My_issues/my_issues_screen.dart index 7c9a237a..c416d48f 100644 --- a/lib/screens/MainScreens/My_issues/my_issues_screen.dart +++ b/lib/screens/MainScreens/My_issues/my_issues_screen.dart @@ -511,6 +511,14 @@ class _MyIssuesScreenState extends ConsumerState { state.leading ?? const SizedBox.shrink(), Container( + constraints: + BoxConstraints( + maxWidth: MediaQuery.of( + context) + .size + .width * + 0.65, + ), padding: EdgeInsets.only( left: issueProvider .issues @@ -519,11 +527,6 @@ class _MyIssuesScreenState extends ConsumerState { ? 0 : 10, ), - width: - MediaQuery.of(context) - .size - .width * - 0.6, child: CustomText( state.title!, overflow: TextOverflow diff --git a/lib/screens/MainScreens/Notification/notification.dart b/lib/screens/MainScreens/Notification/notification.dart index c7441f22..929421b8 100644 --- a/lib/screens/MainScreens/Notification/notification.dart +++ b/lib/screens/MainScreens/Notification/notification.dart @@ -153,6 +153,7 @@ class _NotifiactionScreenState extends ConsumerState unselectedLabelColor: themeProvider.themeManager.placeholderTextColor, labelColor: themeProvider.themeManager.primaryColour, + dividerColor: themeProvider.themeManager.borderSubtle01Color, tabs: const [ Tab( text: 'My Issues', diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart index 01620956..3a6eb901 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart @@ -131,7 +131,7 @@ class _CycleDetailState extends ConsumerState { .then((value) => getChartData(modulesProvider .moduleDetailsData['distribution']['completion_chart'])); - issuesProvider.getIssueProperties( + issuesProvider.getIssueDisplayProperties( issueCategory: IssueCategory.moduleIssues); modulesProvider @@ -174,7 +174,7 @@ class _CycleDetailState extends ConsumerState { ref .read(ProviderList.issuesProvider) - .getIssueProperties(issueCategory: IssueCategory.cycleIssues); + .getIssueDisplayProperties(issueCategory: IssueCategory.cycleIssues); cyclesProvider .filterCycleIssues( cycleID: widget.cycleId!, @@ -209,17 +209,9 @@ class _CycleDetailState extends ConsumerState { final bool isLoading = widget.fromModule ? modulesProvider.moduleState == StateEnum.loading : cyclesProvider.cyclesState == StateEnum.loading; - return WillPopScope( onWillPop: () async { if (widget.from == PreviousScreen.myIssues) return true; - issueProvider.getIssues( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: projectProvider.currentProject['id'], - ); modulesProvider.selectedIssues = []; cyclesProvider.selectedIssues = []; issueProvider.issues.projectView = issueProvider.tempProjectView; @@ -289,13 +281,6 @@ class _CycleDetailState extends ConsumerState { Navigator.pop(context); return; } - issueProvider.getIssues( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: projectProvider.currentProject['id'], - ); modulesProvider.selectedIssues = []; cyclesProvider.selectedIssues = []; issueProvider.issues.projectView = issueProvider.tempProjectView; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart index 705c61f7..d6053d10 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; @@ -805,9 +807,6 @@ Widget issues(BuildContext context, WidgetRef ref, {bool isViews = false}) { issueProvider.initializeBoard(views: isViews); } - // log('Project Issues'); - // log(issueProvider.issues.projectView.toString()); - return LoadingWidget( loading: issueProvider.issuePropertyState == StateEnum.loading || issueProvider.issueState == StateEnum.loading || @@ -833,7 +832,8 @@ Widget issues(BuildContext context, WidgetRef ref, {bool isViews = false}) { issueProvider.projectViewState == StateEnum.loading || issueProvider.orderByState == StateEnum.loading ? Container() - : issueProvider.isISsuesEmpty + : issueProvider.groupByResponse.isEmpty && + issueProvider.issueState == StateEnum.success ? Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -976,7 +976,7 @@ Widget issues(BuildContext context, WidgetRef ref, {bool isViews = false}) { ? Container( margin: const EdgeInsets - .only( + .only( bottom: 10), width: MediaQuery.of( context) @@ -987,7 +987,7 @@ Widget issues(BuildContext context, WidgetRef ref, {bool isViews = false}) { .primaryBackgroundDefaultColor, padding: const EdgeInsets - .only( + .only( top: 15, bottom: 15, left: 15), @@ -1004,7 +1004,7 @@ Widget issues(BuildContext context, WidgetRef ref, {bool isViews = false}) { : Container( margin: const EdgeInsets - .only( + .only( bottom: 10), ) ], diff --git a/lib/screens/MainScreens/Projects/project_screen.dart b/lib/screens/MainScreens/Projects/project_screen.dart index fd633468..7eb2abaf 100644 --- a/lib/screens/MainScreens/Projects/project_screen.dart +++ b/lib/screens/MainScreens/Projects/project_screen.dart @@ -141,6 +141,8 @@ class _ProjectScreenState extends ConsumerState .themeManager.placeholderTextColor, labelColor: themeProvider.themeManager.primaryColour, + dividerColor: themeProvider + .themeManager.borderSubtle01Color, tabs: const [ Tab( text: 'Projects', @@ -152,12 +154,12 @@ class _ProjectScreenState extends ConsumerState text: 'Unjoined', ), ]), - Container( - height: 1, - width: double.infinity, - color: - themeProvider.themeManager.borderSubtle01Color, - ), + // Container( + // height: 1, + // width: double.infinity, + // color: + // Colors.amber + // ), Expanded( child: Padding( padding: diff --git a/lib/screens/on_boarding/auth/setup_workspace.dart b/lib/screens/on_boarding/auth/setup_workspace.dart index a83aae68..ce3542ca 100644 --- a/lib/screens/on_boarding/auth/setup_workspace.dart +++ b/lib/screens/on_boarding/auth/setup_workspace.dart @@ -6,6 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:plane/config/config_variables.dart'; import 'package:plane/screens/on_boarding/auth/invite_co_workers.dart'; +import 'package:plane/utils/bottom_sheet.helper.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_rich_text.dart'; @@ -231,23 +232,12 @@ class _SetupWorkspaceState extends ConsumerState { key: const Key('companySize'), onTap: () { FocusScope.of(context).unfocus(); - showModalBottomSheet( - context: context, - constraints: BoxConstraints( - maxHeight: MediaQuery.of(context) - .size - .height * - 0.5, - ), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20), - ), - ), - builder: (context) { - return const CompanySize(); - }); + BottomSheetHelper.showBottomSheet( + context, + const CompanySize(), + constraints: const BoxConstraints( + maxHeight: 400, + )); }, child: Container( height: 50, diff --git a/lib/utils/bottom_sheet.helper.dart b/lib/utils/bottom_sheet.helper.dart new file mode 100644 index 00000000..972ea653 --- /dev/null +++ b/lib/utils/bottom_sheet.helper.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +class BottomSheetHelper { + static void showBottomSheet( + BuildContext context, + Widget child, { + BoxConstraints? constraints, + Color? barrierColor, + ShapeBorder? shape, + bool? isScrollControlled = false, + bool? isDismissible = true, + bool? enableDrag = true, + }) { + showModalBottomSheet( + constraints: constraints ?? + BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.7), + shape: shape ?? + const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20))), + isScrollControlled: isScrollControlled ?? false, + isDismissible: isDismissible ?? true, + enableDrag: enableDrag ?? true, + context: context, + builder: (BuildContext context) { + return child; + }); + } +} diff --git a/lib/utils/extensions/list_extensions.dart b/lib/utils/extensions/list_extensions.dart index 9c7c2e8f..a7fb92ba 100644 --- a/lib/utils/extensions/list_extensions.dart +++ b/lib/utils/extensions/list_extensions.dart @@ -6,4 +6,10 @@ extension ListExtension on List? { bool isNotNullOrEmpty() { return !isNullOrEmpty(); } + + String toQueryParam(String param) { + if (this!.isEmpty) return ''; + return param + + toString().replaceAll('[', '').replaceAll(']', '').replaceAll(' ', ''); + } } diff --git a/lib/utils/issues_filter/group_by_issues.dart b/lib/utils/issues_filter/group_by_issues.dart new file mode 100644 index 00000000..64d2cc6f --- /dev/null +++ b/lib/utils/issues_filter/group_by_issues.dart @@ -0,0 +1,143 @@ +import 'package:plane/utils/enums.dart'; + +class IssuesGroupBYHelper { + static List defaultStateGroups = [ + 'backlog', + 'unstarted', + 'started', + 'completed', + 'cancelled', + ]; + + static Map> _groupByState( + List issues, Map states) { + Map> groupedIssues = {}; + Map> stateGroups = {}; + for (final state in defaultStateGroups) { + stateGroups[state] = + states.values.where((e) => e['group'] == state).toList(); + stateGroups[state]! + .sort((a, b) => a['sequence'].compareTo(b['sequence'])); + } + for (final stateGroup in stateGroups.keys) { + for (final state in stateGroups[stateGroup]!) { + groupedIssues[state['id']] = + issues.where((issue) => issue['state'] == state['id']).toList(); + } + } + return groupedIssues; + } + + static Map> _groupByStateGroups( + List issues, Map states) { + Map> groupedIssues = {}; + + for (final stateGroup in defaultStateGroups) { + groupedIssues[stateGroup] = []; + } + for (final issue in issues) { + groupedIssues[issue['state_detail']['group']]!.add(issue); + } + + return groupedIssues; + } + + static Map> _groupByPriority(List issues) { + Map> groupedIssues = {}; + final priorities = ['urgent', 'high', 'medium', 'low', 'none']; + for (final priority in priorities) { + groupedIssues[priority] = + issues.where((issue) => issue['priority'] == priority).toList(); + } + return groupedIssues; + } + + static Map> _groupByLabels( + List issues, List labels) { + Map> groupedIssues = {}; + for (final label in labels) { + groupedIssues[label] = issues + .where((issue) => (issue['labels'] as List).contains(label)) + .toList(); + } + return groupedIssues; + } + + static Map> _groupByAssignees( + List issues, List assignees) { + Map> groupedIssues = {}; + for (final assignee in assignees) { + groupedIssues[assignee['member']['id']] = issues + .where((issue) => + (issue['assignees'] as List).contains(assignee['member']['id'])) + .toList(); + } + return groupedIssues; + } + + static Map> _groupByCreator( + List issues, List members) { + Map> groupedIssues = {}; + for (final member in members) { + groupedIssues[member['member']['id']] = issues + .where((issue) => (issue['created_by'] == member['member']['id'])) + .toList(); + } + return groupedIssues; + } + + static Map> _groupByProject( + List issues, List projects) { + Map> groupedIssues = {}; + for (final project in projects) { + groupedIssues[project['id']] = + issues.where((issue) => (issue['project'] == project['id'])).toList(); + } + return groupedIssues; + } + + static Map> _groupByNone(List issues) { + Map> groupedIssues = {}; + groupedIssues['All Issues'] = issues; + return groupedIssues; + } + + static Map> groupIssues( + List issues, + GroupBY groupBY, { + Map? filter, + dynamic labels, + dynamic members, + dynamic projects, + dynamic states, + }) { + Map> groupedIssues = {}; + switch (groupBY) { + case GroupBY.state: + groupedIssues = _groupByState(issues, states); + break; + case GroupBY.stateGroups: + groupedIssues = _groupByStateGroups(issues, states); + break; + case GroupBY.priority: + groupedIssues = _groupByPriority(issues); + break; + case GroupBY.labels: + groupedIssues = _groupByLabels(issues, labels); + break; + case GroupBY.assignees: + groupedIssues = _groupByAssignees(issues, members); + break; + case GroupBY.createdBY: + groupedIssues = _groupByCreator(issues, members); + break; + case GroupBY.project: + groupedIssues = _groupByProject(issues, projects); + break; + case GroupBY.none: + groupedIssues = _groupByNone(issues); + break; + } + return groupedIssues; + } +} diff --git a/lib/utils/issues_filter/issue_filter.helper.dart b/lib/utils/issues_filter/issue_filter.helper.dart new file mode 100644 index 00000000..dd5b4180 --- /dev/null +++ b/lib/utils/issues_filter/issue_filter.helper.dart @@ -0,0 +1,43 @@ +import 'package:plane/models/issues.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/utils/extensions/list_extensions.dart'; +import 'package:plane/utils/issues_filter/group_by_issues.dart'; +import 'package:plane/utils/issues_filter/order_by_issues.dart'; + +class IssueFilterHelper { + static String getFilterQueryParams(Filters filters) { + String url = ''; + url = '$url${filters.priorities.toQueryParam("&priority=")}'; + url = '$url${filters.states.toQueryParam("&state=")}'; + url = '$url${filters.assignees.toQueryParam("&assignees=")}'; + url = '$url${filters.createdBy.toQueryParam("&created_by=")}'; + url = '$url${filters.labels.toQueryParam("&labels=")}'; + url = '$url${filters.targetDate.toQueryParam("&target_date=")}'; + url = '$url${filters.startDate.toQueryParam("&start_date=")}'; + return url; + } + + static Map organizeIssues( + List issues, + GroupBY groupBY, + OrderBY orderBY, { + Map? filter, + dynamic labels, + dynamic members, + dynamic projects, + dynamic states, + }) { + Map> groupedIssues = IssuesGroupBYHelper.groupIssues( + issues, + groupBY, + filter: filter, + labels: labels, + members: members, + projects: projects, + states: states, + ); + Map organizedIssues = + IssuesOrderBYHelper.orderIssues(groupedIssues, orderBY); + return organizedIssues; + } +} diff --git a/lib/utils/issues_filter/order_by_issues.dart b/lib/utils/issues_filter/order_by_issues.dart new file mode 100644 index 00000000..a9b7bd41 --- /dev/null +++ b/lib/utils/issues_filter/order_by_issues.dart @@ -0,0 +1,101 @@ +// ignore_for_file: non_constant_identifier_names +import 'package:plane/utils/enums.dart'; + +class IssuesOrderBYHelper { + static Map> _orderBYManual( + Map> issues) { + issues.forEach((key, value) { + value.sort((a, b) => b['sort_order'].compareTo(a['sort_order'])); + }); + return issues; + } + + static Map> _orderBYLastCreated( + Map> issues) { + issues.forEach((key, value) { + value.sort((a, b) => DateTime.parse(b['created_at']) + .compareTo(DateTime.parse(a['created_at']))); + }); + return issues; + } + + static Map> _orderBYLastUpdated( + Map> issues) { + issues.forEach((key, value) { + value.sort((a, b) => DateTime.parse(b['updated_at']) + .compareTo(DateTime.parse(a['updated_at']))); + }); + return issues; + } + + static Map> _orderBYStartDate( + Map> issues) { + issues.forEach((key, value) { + value.sort((a, b) { + if (a['start_date'] == null && b['start_date'] == null) { + return 0; + } else if (b['start_date'] == null && a['start_date'] != null) { + return -1; + } else if (a['start_date'] == null && b['start_date'] != null) { + return 1; + } + return DateTime.parse(a['start_date']) + .compareTo(DateTime.parse(b['start_date'])); + }); + }); + return issues; + } + + static Map> _orderBYPriority( + Map> issues) { + final ISSUE_PRIORITIES = { + 'urgent': 0, + 'high': 1, + 'medium': 2, + 'low': 3, + 'none': 4 + }; + issues.forEach((key, value) { + value.sort((a, b) { + return ISSUE_PRIORITIES[a['priority']]! + .compareTo(ISSUE_PRIORITIES[b['priority']]!); + }); + }); + return issues; + } + + static Map> orderIssues( + Map> issues, + OrderBY orderBY, { + Map? filter, + dynamic labels, + dynamic members, + dynamic projects, + dynamic states, + }) { + // base issue order + Map> orderedIssues = _orderBYLastCreated(issues); + // order by selected filter + switch (orderBY) { + case OrderBY.manual: + orderedIssues = _orderBYManual(issues); + break; + case OrderBY.lastCreated: + orderedIssues = _orderBYLastCreated(issues); + break; + case OrderBY.lastUpdated: + orderedIssues = _orderBYLastUpdated(issues); + break; + case OrderBY.startDate: + orderedIssues = _orderBYStartDate(issues); + break; + case OrderBY.priority: + orderedIssues = _orderBYPriority(issues); + break; + default: + orderedIssues = _orderBYManual(issues); + break; + } + return orderedIssues; + } +} From f4499c31c05aad248b9ecf15b242077f73581393 Mon Sep 17 00:00:00 2001 From: ramesh kumar Date: Tue, 16 Jan 2024 16:06:14 +0530 Subject: [PATCH 2/7] fix: project, cycles and modules issues fix --- lib/app.dart | 4 +- lib/bottom_sheets/filters/filter_sheet.dart | 18 +- .../filters/filter_sheet_state.dart | 23 +- .../filters/widgets/filter_buttons.dart | 5 +- lib/bottom_sheets/global_search_sheet.dart | 2 +- .../issue_detail_cycles_sheet.dart | 1 + .../issue_detail_modules_list.dart | 1 + lib/bottom_sheets/issues_list_sheet.dart | 2 + .../project_invite_memebers_sheet.dart | 4 +- lib/bottom_sheets/select_project_members.dart | 75 ++--- lib/bottom_sheets/type_sheet.dart | 4 +- lib/bottom_sheets/views_sheet.dart | 62 ++-- lib/config/apis.dart | 8 +- lib/kanban/Provider/board_provider.dart | 3 +- lib/models/issues.dart | 4 +- lib/provider/cycles_provider.dart | 232 +++++++++++++-- lib/provider/issue_provider.dart | 2 +- lib/provider/issues_provider.dart | 182 +++++------- lib/provider/modules_provider.dart | 115 +++++--- lib/provider/my_issues_provider.dart | 2 - lib/provider/projects_provider.dart | 40 ++- .../Profile/User_profile/over_view.dart | 2 +- .../CyclesTab/cycle_active_card.dart | 2 +- ...e_detail.dart => cycle_module_detail.dart} | 128 ++++----- .../CyclesTab/project_details_cycles.dart | 2 +- .../IssuesTab/CreateIssue/create_issue.dart | 11 +- .../ProjectDetail/IssuesTab/issue_detail.dart | 4 +- .../ProjectDetail/ModulesTab/module_card.dart | 2 +- .../ModulesTab/simple_module_card.dart | 2 +- .../ProjectDetail/project_detail.dart | 10 - lib/startup/dependency_resolver.dart | 4 +- lib/utils/issues_filter/group_by_issues.dart | 4 +- lib/widgets/issue_card_widget.dart | 267 ++++++++---------- 33 files changed, 688 insertions(+), 539 deletions(-) rename lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/{cycle_detail.dart => cycle_module_detail.dart} (97%) diff --git a/lib/app.dart b/lib/app.dart index 7d224532..ab3fc064 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -31,7 +31,9 @@ class _AppState extends ConsumerState { final configProvider = ref.watch(ProviderList.configProvider); final themeProvider = ref.watch(ProviderList.themeProvider); return Scaffold( - body: (configProvider.getConfigState == StateEnum.loading || + body: ( + // TODO -> Config API should be re-initiated once the API added in this base API + // configProvider.getConfigState == StateEnum.loading || profileProv.getProfileState == StateEnum.loading || workspaceProv.workspaceInvitationState == StateEnum.loading) ? Center( diff --git a/lib/bottom_sheets/filters/filter_sheet.dart b/lib/bottom_sheets/filters/filter_sheet.dart index dd881f27..41173514 100644 --- a/lib/bottom_sheets/filters/filter_sheet.dart +++ b/lib/bottom_sheets/filters/filter_sheet.dart @@ -36,18 +36,21 @@ part 'widgets/labels_filter.dart'; // ignore: must_be_immutable class FilterSheet extends ConsumerStatefulWidget { - FilterSheet( - {super.key, - required this.issueCategory, - this.filtersData, - this.fromViews = false, - this.isArchived = false, - this.fromCreateView = false}); + FilterSheet({ + super.key, + required this.issueCategory, + this.filtersData, + this.fromViews = false, + this.isArchived = false, + this.fromCreateView = false, + this.cycleOrModuleId, + }); final IssueCategory issueCategory; final bool fromCreateView; final bool fromViews; final bool isArchived; dynamic filtersData; + String? cycleOrModuleId; @override ConsumerState createState() => _FilterSheetState(); } @@ -158,6 +161,7 @@ class _FilterSheetState extends ConsumerState { _applyFilterButton( state: state, context: context, + cycleOrModuleId: widget.cycleOrModuleId ) ], ), diff --git a/lib/bottom_sheets/filters/filter_sheet_state.dart b/lib/bottom_sheets/filters/filter_sheet_state.dart index ff8c0d67..1156ebd1 100644 --- a/lib/bottom_sheets/filters/filter_sheet_state.dart +++ b/lib/bottom_sheets/filters/filter_sheet_state.dart @@ -185,7 +185,8 @@ class _FilterState { } } - void _applyFilters(BuildContext context) { + void _applyFilters( + {required BuildContext context, String? cycleOrModuleId}) async { final MyIssuesProvider myIssuesProvider = ref.read(ProviderList.myIssuesProvider); final IssuesProvider issuesProvider = ref.read(ProviderList.issuesProvider); @@ -207,20 +208,18 @@ class _FilterState { } issueCategory == IssueCategory.myIssues ? myIssuesProvider.issues.filters = filters - : issuesProvider.issues.filters = filters; + : issueCategory == IssueCategory.cycleIssues + ? cyclesProvider.issues.filters = filters + : issueCategory == IssueCategory.moduleIssues + ? modulesProvider.issues.filters = filters + : issuesProvider.issues.filters = filters; if (issueCategory == IssueCategory.cycleIssues) { - cyclesProvider - .filterCycleIssues( - slug: slug, - projectId: projID, - ) - .then((value) => cyclesProvider.initializeBoard()); + // cyclesProvider.updateProjectView(); + cyclesProvider.filterCycleIssues( + slug: slug, projectId: projID, ref: ref, cycleID: cycleOrModuleId); } else if (issueCategory == IssueCategory.moduleIssues) { modulesProvider - .filterModuleIssues( - slug: slug, - projectId: projID, - ) + .filterModuleIssues(slug: slug, projectId: projID, ref: ref) .then((value) => modulesProvider.initializeBoard()); } else if (issueCategory == IssueCategory.myIssues) { myIssuesProvider.updateMyIssueView(); diff --git a/lib/bottom_sheets/filters/widgets/filter_buttons.dart b/lib/bottom_sheets/filters/widgets/filter_buttons.dart index c6a00e92..c8b48cc2 100644 --- a/lib/bottom_sheets/filters/widgets/filter_buttons.dart +++ b/lib/bottom_sheets/filters/widgets/filter_buttons.dart @@ -18,7 +18,7 @@ Widget _clearFilterButton( stateGroup: [], subscriber: [], ); - state._applyFilters(ref.context); + state._applyFilters(context: ref.context); }, child: Container( height: 35, @@ -97,6 +97,7 @@ Widget _saveView({required _FilterState state, required WidgetRef ref}) { Widget _applyFilterButton({ required _FilterState state, required BuildContext context, + String? cycleOrModuleId }) { return Container( height: 50, @@ -107,7 +108,7 @@ Widget _applyFilterButton({ child: Button( text: state.fromCreateView ? 'Add Filter' : 'Apply Filter', ontap: () { - state._applyFilters(context); + state._applyFilters(context:context, cycleOrModuleId: cycleOrModuleId ?? ''); }, textColor: Colors.white, ), diff --git a/lib/bottom_sheets/global_search_sheet.dart b/lib/bottom_sheets/global_search_sheet.dart index 7578f706..8e4656db 100644 --- a/lib/bottom_sheets/global_search_sheet.dart +++ b/lib/bottom_sheets/global_search_sheet.dart @@ -13,7 +13,7 @@ import 'package:plane/screens/Import%20&%20Export/import_export.dart'; import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/members.dart'; import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/workspace_general.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/create_cycle.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ModulesTab/create_module.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart'; diff --git a/lib/bottom_sheets/issue_detail_cycles_sheet.dart b/lib/bottom_sheets/issue_detail_cycles_sheet.dart index 452dccd4..272e7e37 100644 --- a/lib/bottom_sheets/issue_detail_cycles_sheet.dart +++ b/lib/bottom_sheets/issue_detail_cycles_sheet.dart @@ -110,6 +110,7 @@ class _IssueDetailCyclesListState extends ConsumerState { slug: workspaceProvider.selectedWorkspace.workspaceSlug, projectId: projectProvider.currentProject['id'], + ref: ref ); issuesProvider.filterIssues( slug: workspaceProvider diff --git a/lib/bottom_sheets/issue_detail_modules_list.dart b/lib/bottom_sheets/issue_detail_modules_list.dart index a15ed8e2..92f2be9a 100644 --- a/lib/bottom_sheets/issue_detail_modules_list.dart +++ b/lib/bottom_sheets/issue_detail_modules_list.dart @@ -101,6 +101,7 @@ class _IssueDetailMoudlesListState slug: workspaceProvider.selectedWorkspace.workspaceSlug, projectId: projectProvider.currentProject['id'], + ref: ref ); issuesProvider.filterIssues( slug: workspaceProvider diff --git a/lib/bottom_sheets/issues_list_sheet.dart b/lib/bottom_sheets/issues_list_sheet.dart index cb6d1031..9a021860 100644 --- a/lib/bottom_sheets/issues_list_sheet.dart +++ b/lib/bottom_sheets/issues_list_sheet.dart @@ -490,6 +490,7 @@ class _IssuesListSheetState extends ConsumerState { .watch(ProviderList .projectProvider) .currentProject['id'], + ref: ref ); issuesProvider.filterIssues( slug: ref @@ -536,6 +537,7 @@ class _IssuesListSheetState extends ConsumerState { .read(ProviderList .projectProvider) .currentProject['id'], + ref: ref ); issuesProvider.filterIssues( slug: ref diff --git a/lib/bottom_sheets/project_invite_memebers_sheet.dart b/lib/bottom_sheets/project_invite_memebers_sheet.dart index c3cbda0e..a4306a19 100644 --- a/lib/bottom_sheets/project_invite_memebers_sheet.dart +++ b/lib/bottom_sheets/project_invite_memebers_sheet.dart @@ -343,8 +343,8 @@ class _ProjectInviteMembersSheetState projectProvider.getProjectMembers( slug: workspaceProvider .selectedWorkspace.workspaceSlug, - projId: - projectProvider.projectDetailModel!.id!); + projId: projectProvider.projectDetailModel!.id!, + ); } else { CustomToast.showToast( mainBuildContext, diff --git a/lib/bottom_sheets/select_project_members.dart b/lib/bottom_sheets/select_project_members.dart index d72191c2..edc24123 100644 --- a/lib/bottom_sheets/select_project_members.dart +++ b/lib/bottom_sheets/select_project_members.dart @@ -26,18 +26,19 @@ class _SelectProjectMembersState extends ConsumerState { @override void initState() { - if (ref.read(ProviderList.issuesProvider).members.isEmpty || + if (ref.read(ProviderList.projectProvider).projectMembers.isEmpty || widget.createIssue) { - ref.read(ProviderList.issuesProvider).getProjectMembers( + ref.read(ProviderList.projectProvider).getProjectMembers( slug: ref .read(ProviderList.workspaceProvider) .selectedWorkspace .workspaceSlug, - projID: widget.createIssue + projId: widget.createIssue ? ref .read(ProviderList.issuesProvider) .createIssueProjectData['id'] - : ref.read(ProviderList.projectProvider).currentProject['id']); + : ref.read(ProviderList.projectProvider).currentProject['id'], + ); } selectedMembers = ref.read(ProviderList.issuesProvider).createIssuedata['members'] ?? {}; @@ -60,6 +61,7 @@ class _SelectProjectMembersState extends ConsumerState { final issuesProvider = ref.watch(ProviderList.issuesProvider); final issueProvider = ref.watch(ProviderList.issueProvider); final themeProvider = ref.watch(ProviderList.themeProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); return WillPopScope( onWillPop: () async { issuesProvider.createIssuedata['members'] = @@ -106,7 +108,7 @@ class _SelectProjectMembersState extends ConsumerState { child: ListView( children: [ ListView.builder( - itemCount: issuesProvider.members.length, + itemCount: projectProvider.projectMembers.length, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, @@ -115,37 +117,42 @@ class _SelectProjectMembersState extends ConsumerState { onTap: () { if (widget.createIssue) { setState(() { - if (selectedMembers[ - issuesProvider.members[index] - ['member']['id']] == + if (selectedMembers[projectProvider + .projectMembers[index] + ['member']['id']] == null) { - selectedMembers[issuesProvider - .members[index]['member']['id']] = { - "avatar": - issuesProvider.members[index] - ['member']['avatar'], - "display_name": - issuesProvider.members[index] - ['member']['display_name'], - "id": issuesProvider.members[index] + selectedMembers[projectProvider + .projectMembers[index]['member'] + ['id']] = { + "avatar": projectProvider + .projectMembers[index] + ['member']['avatar'], + "display_name": projectProvider + .projectMembers[index] + ['member']['display_name'], + "id": projectProvider + .projectMembers[index] ['member']['id'] }; } else { - selectedMembers.remove(issuesProvider - .members[index]['member']['id']); + selectedMembers.remove(projectProvider + .projectMembers[index]['member'] + ['id']); } }); } else { setState(() { if (issueDetailSelectedMembers.contains( - issuesProvider.members[index] + projectProvider.projectMembers[index] ['member']['id'])) { issueDetailSelectedMembers.remove( - issuesProvider.members[index] + projectProvider + .projectMembers[index] ['member']['id']); } else { issueDetailSelectedMembers.add( - issuesProvider.members[index] + projectProvider + .projectMembers[index] ['member']['id']); } }); @@ -166,14 +173,15 @@ class _SelectProjectMembersState extends ConsumerState { width: 30, child: MemberLogoWidget( padding: EdgeInsets.zero, - imageUrl: - issuesProvider.members[index] - ['member']['avatar'], + imageUrl: projectProvider + .projectMembers[index] + ['member']['avatar'], colorForErrorWidget: const Color.fromRGBO( 55, 65, 81, 1), memberNameFirstLetterForErrorWidget: - issuesProvider.members[index] + projectProvider + .projectMembers[index] ['member'] ['display_name'][0] .toString() @@ -186,7 +194,8 @@ class _SelectProjectMembersState extends ConsumerState { SizedBox( width: width * 0.7, child: CustomText( - issuesProvider.members[index] + projectProvider + .projectMembers[index] ['member']['display_name'], type: FontStyle.Medium, fontWeight: FontWeightt.Regular, @@ -222,7 +231,7 @@ class _SelectProjectMembersState extends ConsumerState { ], ), ), - issuesProvider.membersState == StateEnum.loading + projectProvider.projectMembersState == StateEnum.loading ? Container( alignment: Alignment.center, color: themeProvider @@ -292,8 +301,10 @@ class _SelectProjectMembersState extends ConsumerState { } Widget createIsseuSelectedMembersWidget(int idx) { - final issuesProvider = ref.watch(ProviderList.issuesProvider); - return selectedMembers[issuesProvider.members[idx]['member']['id']] != null + final projectProvider = ref.watch(ProviderList.projectProvider); + return selectedMembers[projectProvider.projectMembers[idx]['member'] + ['id']] != + null ? const Icon( Icons.done, color: Color.fromRGBO(8, 171, 34, 1), @@ -302,9 +313,9 @@ class _SelectProjectMembersState extends ConsumerState { } Widget issueDetailSelectedMembersWidget(int idx) { - final issuesProvider = ref.read(ProviderList.issuesProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); return issueDetailSelectedMembers - .contains(issuesProvider.members[idx]['member']['id']) + .contains(projectProvider.projectMembers[idx]['member']['id']) ? const Icon( Icons.done, color: Color.fromRGBO(8, 171, 34, 1), diff --git a/lib/bottom_sheets/type_sheet.dart b/lib/bottom_sheets/type_sheet.dart index 923fb37a..33ded9ec 100644 --- a/lib/bottom_sheets/type_sheet.dart +++ b/lib/bottom_sheets/type_sheet.dart @@ -95,13 +95,13 @@ class _TypeSheetState extends ConsumerState { ref .read(ProviderList.modulesProvider) .filterModuleIssues( - slug: worspaceSlug, projectId: projID); + slug: worspaceSlug, projectId: projID, ref: ref); } else if (widget.issueCategory == IssueCategory.cycleIssues) { ref .read(ProviderList.cyclesProvider) .filterCycleIssues( - slug: worspaceSlug, projectId: projID); + slug: worspaceSlug, projectId: projID, ref: ref); } else if (widget.issueCategory == IssueCategory.issues || widget.issueCategory == IssueCategory.views) { diff --git a/lib/bottom_sheets/views_sheet.dart b/lib/bottom_sheets/views_sheet.dart index 1549907d..d127fa89 100644 --- a/lib/bottom_sheets/views_sheet.dart +++ b/lib/bottom_sheets/views_sheet.dart @@ -2,6 +2,7 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/models/global_search_modal.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/models/issues.dart'; @@ -780,14 +781,12 @@ class _ViewsSheetState extends ConsumerState { issueProvider.getProjectView(reset: true).then((value) { if (widget.issueCategory == IssueCategory.cycleIssues) { cyclesProvider.filterCycleIssues( - slug: slug, - projectId: projID, - ); + slug: slug, projectId: projID, ref: ref); } else if (widget.issueCategory == IssueCategory.moduleIssues) { modulesProvider.filterModuleIssues( slug: slug, - projectId: projID, + projectId: projID, ref: ref, ); } else { issueProvider.filterIssues( @@ -827,14 +826,13 @@ class _ViewsSheetState extends ConsumerState { if (widget.issueCategory == IssueCategory.cycleIssues) { cyclesProvider.filterCycleIssues( - slug: slug, - projectId: projID, - ); + slug: slug, projectId: projID, ref: ref); } else if (widget.issueCategory == IssueCategory.moduleIssues) { modulesProvider.filterModuleIssues( slug: slug, projectId: projID, + ref: ref ); } else { issueProvider.filterIssues( @@ -959,14 +957,7 @@ class _ViewsSheetState extends ConsumerState { }); myIssuesProvider.filterIssues(); } - } else if (issueProvider.issues.groupBY != - Issues.toGroupBY(groupBy) || - issueProvider.issues.orderBY != - Issues.toOrderBY(orderBy) || - issueProvider.issues.issueType != - Issues.toIssueType(issueType) || - issueProvider.showEmptyStates != showEmptyStates || - issueProvider.issues.showSubIssues != showSubIssues) { + } else { setState(() { issueProvider.issues.orderBY = Issues.toOrderBY(orderBy); @@ -978,26 +969,16 @@ class _ViewsSheetState extends ConsumerState { issueProvider.issues.showSubIssues = showSubIssues; }); if (widget.issueCategory == IssueCategory.cycleIssues) { - cyclesProvider.filterCycleIssues( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: ref - .read(ProviderList.projectProvider) - .currentProject["id"], - ); + setState(() { + cyclesProvider.issues.groupBY = + Issues.toGroupBY(groupBy); + cyclesProvider.issues.orderBY = + Issues.toOrderBY(orderBy); + }); + cyclesProvider.applyCycleIssuesView(ref: ref); } else if (widget.issueCategory == IssueCategory.moduleIssues) { - modulesProvider.filterModuleIssues( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: ref - .read(ProviderList.projectProvider) - .currentProject["id"], - ); + modulesProvider.applyModuleIssuesView(ref: ref); } else { issueProvider.applyIssueView(); } @@ -1028,12 +1009,12 @@ class _ViewsSheetState extends ConsumerState { myIssuesProvider.updateMyIssueView(); } else { if (widget.issueCategory == IssueCategory.cycleIssues) { - issueProvider.updateIssueProperties( - properties: properties, - issueCategory: widget.issueCategory, - ); - cyclesProvider.issues.displayProperties = properties; - cyclesProvider.showEmptyStates = showEmptyStates; + // issueProvider.updateIssueProperties( + // properties: properties, + // issueCategory: widget.issueCategory, + // ); + // cyclesProvider.issues.displayProperties = properties; + // cyclesProvider.showEmptyStates = showEmptyStates; } else if (widget.issueCategory == IssueCategory.moduleIssues) { issueProvider.updateIssueProperties( @@ -1055,9 +1036,6 @@ class _ViewsSheetState extends ConsumerState { issueProvider.updateProjectView(); } } - - log(displayProperties.toString()); - Navigator.of(context).pop(); }, textColor: Colors.white, diff --git a/lib/config/apis.dart b/lib/config/apis.dart index 73b0e32c..66c608f9 100644 --- a/lib/config/apis.dart +++ b/lib/config/apis.dart @@ -44,6 +44,8 @@ class APIs { '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/members/'; static String userIssueView = '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/project-members/me'; + static String cycleIssueView = + '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/cycles/\$CYCLEID/user-properties/'; static String myIssuesView = '$baseApi/api/workspaces/\$SLUG/workspace-members/me/'; static String updateMyIssuesView = @@ -67,7 +69,7 @@ class APIs { static String projectViews = '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/project-views/'; static String issueDisplayProperties = - '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/issue-display-properties/'; + '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/user-properties/'; static String issueDetails = '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/issues/\$ISSUEID/'; static String subIssues = @@ -82,9 +84,9 @@ class APIs { static String toggleFavoriteCycle = '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/user-favorite-cycles/'; static String orderByGroupByCycleIssues = - '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/cycles/\$CYCLEID/cycle-issues/?order_by=\$ORDERBY&group_by=\$GROUPBY&type=\$TYPE/'; + '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/cycles/\$CYCLEID/cycle-issues/?type=\$TYPE/'; static String orderByGroupByModuleIssues = - '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/modules/\$MODULEID/module-issues/?order_by=\$ORDERBY&group_by=\$GROUPBY&type=\$TYPE/'; + '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/modules/\$MODULEID/module-issues/?type=\$TYPE/'; static String myIssues = '$baseApi/api/workspaces/\$SLUG/my-issues/?order_by=\$ORDERBY&group_by=\$GROUPBY&type=\$TYPE'; static String projectIdentifier = diff --git a/lib/kanban/Provider/board_provider.dart b/lib/kanban/Provider/board_provider.dart index c4b6ce22..71a83914 100644 --- a/lib/kanban/Provider/board_provider.dart +++ b/lib/kanban/Provider/board_provider.dart @@ -82,7 +82,7 @@ class BoardProvider extends ChangeNotifier { required bool groupEmptyStates}) { var themeProvider = ref.read(ProviderList.themeProvider); board = BoardState( - boardID: boardID, + boardID: boardID, textStyle: textStyle, lists: [], isCardsDraggable: isCardsDraggable, @@ -110,7 +110,6 @@ class BoardProvider extends ChangeNotifier { cardPlaceHolderDecoration: cardPlaceHolderDecoration, listDecoration: listDecoration, boardDecoration: boardDecoration); - // log("LENGTH=${data.length}"); BoardList emptyStates = BoardList( // footer: data[i].footer, index: double.maxFinite.toInt(), diff --git a/lib/models/issues.dart b/lib/models/issues.dart index 55789269..58056122 100644 --- a/lib/models/issues.dart +++ b/lib/models/issues.dart @@ -156,8 +156,8 @@ class Issues { switch (groupBY) { case "state": return GroupBY.state; - case "state_detail.group": - return GroupBY.stateGroups; + // case "state_detail.group": + // return GroupBY.stateGroups; case "priority": return GroupBY.priority; case "labels": diff --git a/lib/provider/cycles_provider.dart b/lib/provider/cycles_provider.dart index f408a912..ec1df444 100644 --- a/lib/provider/cycles_provider.dart +++ b/lib/provider/cycles_provider.dart @@ -34,6 +34,7 @@ class CyclesProvider with ChangeNotifier { StateEnum completedCyclesState = StateEnum.loading; StateEnum draftCyclesState = StateEnum.loading; StateEnum transferIssuesState = StateEnum.empty; + StateEnum cycleViewState = StateEnum.empty; List cyclesAllData = []; List cycleFavoriteData = []; List cycleUpcomingFavoriteData = []; @@ -47,6 +48,7 @@ class CyclesProvider with ChangeNotifier { List cyclesDraftData = []; Map cyclesDetailsData = {}; Map currentCycle = {}; + Map cycleView = {}; int cyclesTabIndex = 0; Issues issues = Issues.initialize(); List issuesResponse = []; @@ -59,6 +61,8 @@ class CyclesProvider with ChangeNotifier { int cycleDetailSelectedIndex = 0; List queries = ['all', 'current', 'upcoming', 'completed', 'draft']; List loadingCycleId = []; + Enum issueCategory = IssueCategory.cycleIssues; + void setState() { notifyListeners(); } @@ -268,10 +272,10 @@ class CyclesProvider with ChangeNotifier { Map? data, }) async { try { - if (!disableLoading) { - cyclesDetailState = StateEnum.loading; - notifyListeners(); - } + // if (!disableLoading) { + cyclesDetailState = StateEnum.loading; + notifyListeners(); + // } final url = '${APIs.cycles.replaceFirst('\$SLUG', slug).replaceFirst('\$PROJECTID', projectId)}$cycleId/'; final response = await DioConfig().dioServe( @@ -386,6 +390,9 @@ class CyclesProvider with ChangeNotifier { // log(issues.groupBY.name); issues.issues = []; issuesResponse = []; + final projectMembers = + ref!.read(ProviderList.projectProvider).projectMembers; + for (int j = 0; j < filterIssues.length; j++) { final List items = []; final groupedIssues = filterIssues.values.toList()[j]; @@ -415,20 +422,18 @@ class CyclesProvider with ChangeNotifier { } } - for (int i = 0; i < issuesProvider.members.length; i++) { - if (groupID == issuesProvider.members[i]['member']['id']) { - userName = issuesProvider.members[i]['member']['first_name'] + + for (int i = 0; i < projectMembers.length; i++) { + if (groupID == projectMembers[i]['member']['id']) { + userName = projectMembers[i]['member']['first_name'] + ' ' + - issuesProvider.members[i]['member']['last_name']; + projectMembers[i]['member']['last_name']; userName = userName.trim().isEmpty - ? issuesProvider.members[i]['member']['email'] + ? projectMembers[i]['member']['email'] : userName; userFound = true; break; } } - //log('RESPONSE : ' + filterIssues.toString()); - // log('================================================================ ${stateOrdering[j]}'); var title = issues.groupBY == GroupBY.priority ? groupID : issues.groupBY == GroupBY.state @@ -681,7 +686,6 @@ class CyclesProvider with ChangeNotifier { newList[newCardIndex]['label_details'] = labelDetails; - log(response.data.toString()); if (issues.groupBY == GroupBY.priority) { log(newList[newCardIndex]['name']); newList[newCardIndex]['priority'] = @@ -703,7 +707,6 @@ class CyclesProvider with ChangeNotifier { } }); } - log("ISSUE REPOSITIONED"); notifyListeners(); } on DioException catch (err) { filterIssues.values.elementAt(oldListIndex).insert(oldCardIndex, @@ -802,35 +805,132 @@ class CyclesProvider with ChangeNotifier { } } - void applyCycleIssuesView() { - final issuesProvider = ref!.read(ProviderList.issuesProvider); + Future getCycleView({bool reset = false, required String cycleId}) async { + cycleViewState = StateEnum.loading; + if (reset) { + notifyListeners(); + } + try { + var url = APIs.cycleIssueView + .replaceAll( + "\$SLUG", + ref! + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug) + .replaceAll('\$PROJECTID', + ref!.read(ProviderList.projectProvider).currentProject['id']) + .replaceAll('\$CYCLEID', cycleId); + log('THIS IS CYCLE VIEW URL: $url'); + final response = await DioConfig().dioServe( + hasAuth: true, + url: url, + hasBody: false, + httpMethod: HttpMethod.get, + ); + log(response.toString()); + cycleView = response.data; + issues.projectView = cycleView['display_filters']['layout'] == 'list' + ? ProjectView.list + : cycleView['display_filters']['layout'] == 'calendar' + ? ProjectView.calendar + : cycleView['display_filters']['layout'] == 'spreadsheet' + ? ProjectView.spreadsheet + : ProjectView.kanban; + issues.showSubIssues = cycleView['display_filters']['sub_issue'] ?? true; + issues.groupBY = + Issues.toGroupBY(cycleView["display_filters"]["group_by"]); + issues.orderBY = + Issues.toOrderBY(cycleView["display_filters"]["order_by"]); + issues.issueType = + Issues.toIssueType(cycleView["display_filters"]["type"]); + issues.filters.priorities = (cycleView["filters"]["priority"] == 'none' + ? [] + : cycleView["filters"]["priority"]) ?? + []; + issues.filters.states = cycleView["filters"]["state"] ?? []; + issues.filters.assignees = cycleView["filters"]["assignees"] ?? []; + issues.filters.createdBy = cycleView["filters"]["created_by"] ?? []; + issues.filters.labels = cycleView["filters"]["labels"] ?? []; + issues.filters.targetDate = cycleView["filters"]["target_date"] ?? []; + issues.filters.startDate = cycleView["filters"]["start_date"] ?? []; + issues.filters.subscriber = cycleView["filters"]["subscriber"] ?? []; + issues.filters.stateGroup = cycleView["filters"]["state_group"] ?? []; + showEmptyStates = cycleView["display_filters"]["show_empty_groups"]; + + if (issues.groupBY == GroupBY.none) { + issues.projectView = ProjectView.list; + } + if (reset) { + updateCycleView(); + } + cycleViewState = StateEnum.success; + notifyListeners(); + } on DioException catch (e) { + log(e.response.toString()); + issues.projectView = ProjectView.kanban; + cycleViewState = StateEnum.error; + notifyListeners(); + } + } + + void applyCycleIssuesView({required WidgetRef ref}) { + final issuesProvider = ref.watch(ProviderList.issuesProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); final labelIds = issuesProvider.labels.map((e) => e['id']).toList(); filterIssues = IssueFilterHelper.organizeIssues( cycleIssuesList, issues.groupBY, issues.orderBY, labels: labelIds, - members: issuesProvider.members, + members: projectProvider.projectMembers, states: issuesProvider.states); + notifyListeners(); } - Future filterCycleIssues({ - required String slug, - required String projectId, - String? cycleID, - String? moduleID, - // required Map data, - }) async { + Future filterCycleIssues( + {required String slug, + required String projectId, + String? cycleID, + required WidgetRef ref + // required Map data, + }) async { cyclesIssueState = StateEnum.loading; notifyListeners(); - try { - final issuesProvider = ref!.read(ProviderList.issuesProvider); - filterIssues = await issuesProvider.filterIssues( + final issuesProvider = ref.read(ProviderList.issuesProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + if (issues.groupBY == GroupBY.labels) { + issuesProvider.getLabels(slug: slug, projID: projectId); + } else if (issues.groupBY == GroupBY.createdBY) { + projectProvider.getProjectMembers(slug: slug, projId: projectId); + } else if (issues.groupBY == GroupBY.state) { + issuesProvider.getStates( slug: slug, projID: projectId, - cycleId: cycleID, - moduleId: moduleID, - issueCategory: IssueCategory.cycleIssues, + showLoading: false, ); + } + String url; + url = APIs.orderByGroupByCycleIssues + .replaceAll("\$SLUG", slug) + .replaceAll('\$PROJECTID', projectId) + .replaceAll('\$CYCLEID', cycleID!) + .replaceAll('\$TYPE', Issues.fromIssueType(issues.issueType)); + url = '$url&sub_issue=${issues.showSubIssues}&show_empty_groups=true'; + try { + final response = await DioConfig().dioServe( + hasAuth: true, + url: url, + hasBody: false, + httpMethod: HttpMethod.get, + ); + // log('CYCLE ISSUES RESPONSE: ${response.data}'); + cycleIssuesList = response.data; + final organizedIssues = IssueFilterHelper.organizeIssues( + cycleIssuesList, issues.groupBY, issues.orderBY, + labels: issuesProvider.labels.map((e) => e['id']).toList(), + members: projectProvider.projectMembers, + states: issuesProvider.states); + filterIssues = organizedIssues; issuesResponse = []; isIssuesEmpty = true; if (issues.groupBY != GroupBY.none) { @@ -868,6 +968,80 @@ class CyclesProvider with ChangeNotifier { } } + Future updateCycleView( + {bool isArchive = false, bool setDefault = false}) async { + final Map view = { + "view_props": { + "calendarDateRange": "", + "collapsed": false, + "filterIssue": null, + "filters": { + // 'type': null, + // "priority": filterPriority, + if (issues.filters.priorities.isNotEmpty) + "priority": issues.filters.priorities, + if (issues.filters.states.isNotEmpty) "state": issues.filters.states, + if (issues.filters.assignees.isNotEmpty) + "assignees": issues.filters.assignees, + if (issues.filters.createdBy.isNotEmpty) + "created_by": issues.filters.createdBy, + if (issues.filters.labels.isNotEmpty) "labels": issues.filters.labels, + if (issues.filters.targetDate.isNotEmpty) + "target_date": issues.filters.targetDate, + if (issues.filters.startDate.isNotEmpty) + "start_date": issues.filters.startDate, + if (issues.filters.subscriber.isNotEmpty) + "subscriber": issues.filters.subscriber, + if (issues.filters.stateGroup.isNotEmpty) + "state_group": issues.filters.stateGroup, + }, + "display_filters": { + "group_by": Issues.fromGroupBY(issues.groupBY), + "order_by": Issues.fromOrderBY(issues.orderBY), + "type": Issues.fromIssueType(issues.issueType), + "show_empty_groups": showEmptyStates, + if (!isArchive) + "layout": issues.projectView == ProjectView.kanban + ? 'kanban' + : issues.projectView == ProjectView.list + ? 'list' + : issues.projectView == ProjectView.calendar + ? 'calendar' + : 'spreadsheet', + "sub_issue": false, + }, + } + }; + if (setDefault) { + view['default_props'] = view['view_props']; + } + try { + await DioConfig().dioServe( + hasAuth: true, + url: APIs.cycleIssueView + .replaceAll( + "\$SLUG", + ref! + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug) + .replaceAll('\$PROJECTID', + ref!.read(ProviderList.projectProvider).currentProject['id']) + .replaceAll('\$CYCLEID', currentCycle['id']), + hasBody: true, + data: view, + httpMethod: HttpMethod.post, + ); + cycleViewState = StateEnum.success; + notifyListeners(); + } on DioException catch (e) { + log(e.response.toString()); + cycleViewState = StateEnum.error; + notifyListeners(); + } + notifyListeners(); + } + bool isTagsEnabled() { return issues.displayProperties.assignee || issues.displayProperties.dueDate || diff --git a/lib/provider/issue_provider.dart b/lib/provider/issue_provider.dart index deebe07b..9210a2f5 100644 --- a/lib/provider/issue_provider.dart +++ b/lib/provider/issue_provider.dart @@ -19,7 +19,7 @@ import 'package:plane/config/apis.dart'; import 'package:plane/services/dio_service.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart'; +import '../screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; import '../utils/global_functions.dart'; // import 'package:webview_cookie_manager/webview_cookie_manager.dart'; diff --git a/lib/provider/issues_provider.dart b/lib/provider/issues_provider.dart index c36ef27a..1ebc8a0b 100644 --- a/lib/provider/issues_provider.dart +++ b/lib/provider/issues_provider.dart @@ -26,7 +26,6 @@ class IssuesProvider extends ChangeNotifier { IssuesProvider(ChangeNotifierProviderRef this.ref); Ref? ref; StateEnum statesState = StateEnum.empty; - StateEnum membersState = StateEnum.empty; StateEnum issueState = StateEnum.empty; StateEnum labelState = StateEnum.empty; StateEnum orderByState = StateEnum.empty; @@ -65,7 +64,7 @@ class IssuesProvider extends ChangeNotifier { List labels = []; Map states = {}; Map statesData = {}; - List members = []; + // List members = []; Map projectView = {}; Map groupByResponse = {}; List shrinkStates = []; @@ -176,7 +175,6 @@ class IssuesProvider extends ChangeNotifier { labels = []; states = {}; statesData = {}; - members = []; projectView = {}; groupByResponse = {}; @@ -215,6 +213,8 @@ class IssuesProvider extends ChangeNotifier { int count = 0; issuesResponse = []; issues.issues = []; + final projectMembers = + ref!.read(ProviderList.projectProvider).projectMembers; for (int j = 0; j < groupByResponse.length; j++) { final List items = []; final groupedIssues = groupByResponse.values.elementAt(j); @@ -246,13 +246,11 @@ class IssuesProvider extends ChangeNotifier { } } - for (int i = 0; i < members.length; i++) { - if (groupID == members[i]['member']['id']) { - userName = members[i]['member']['first_name'] + - ' ' + - members[i]['member']['last_name']; + for (int i = 0; i < projectMembers.length; i++) { + if (groupID == projectMembers[i]['member']) { + userName = projectMembers[i]['member']['display_name']; userName = userName.trim().isEmpty - ? members[i]['member']['email'] + ? projectMembers[i]['member']['email'] : userName; userFound = true; break; @@ -820,10 +818,10 @@ class IssuesProvider extends ChangeNotifier { ); ref.read(ProviderList.modulesProvider).filterModuleIssues( - slug: slug, - projectId: - ref.read(ProviderList.projectProvider).currentProject["id"], - ); + slug: slug, + projectId: + ref.read(ProviderList.projectProvider).currentProject["id"], + ref: ref); filterIssues( slug: ref .read(ProviderList.workspaceProvider) @@ -839,10 +837,9 @@ class IssuesProvider extends ChangeNotifier { projId: projID, issues: [response.data['id']], ); - ref.read(ProviderList.cyclesProvider).filterCycleIssues( - slug: slug, - projectId: projID, - ); + ref + .read(ProviderList.cyclesProvider) + .filterCycleIssues(slug: slug, projectId: projID, ref: ref); filterIssues( slug: slug, projID: projID, @@ -923,39 +920,6 @@ class IssuesProvider extends ChangeNotifier { } } - Future getProjectMembers({ - required String slug, - required String projID, - }) async { - membersState = StateEnum.loading; - //notifyListeners(); - try { - final response = await DioConfig().dioServe( - hasAuth: true, - url: APIs.projectMembers - .replaceAll("\$SLUG", slug) - .replaceAll('\$PROJECTID', projID), - hasBody: false, - httpMethod: HttpMethod.get, - ); - members = response.data; - for (final element in members) { - if (element["member"]['id'] == - ref!.read(ProviderList.profileProvider).userProfile.id) { - ref!.read(ProviderList.projectProvider).role = - roleParser(role: element["role"]); - break; - } - } - membersState = StateEnum.success; - notifyListeners(); - } on DioException catch (e) { - log(e.response.toString()); - membersState = StateEnum.error; - notifyListeners(); - } - } - Future getIssueDisplayProperties({required Enum issueCategory}) async { final cyclesProvider = ref!.read(ProviderList.cyclesProvider); final modulesProvider = ref!.read(ProviderList.modulesProvider); @@ -1016,114 +980,114 @@ class IssuesProvider extends ChangeNotifier { } else { issueProperty = response.data; issues.displayProperties.assignee = - issueProperty['properties']['assignee']; + issueProperty['display_properties']['assignee']; issues.displayProperties.dueDate = - issueProperty['properties']['due_date']; - issues.displayProperties.id = issueProperty['properties']['key']; + issueProperty['display_properties']['due_date']; + issues.displayProperties.id = issueProperty['display_properties']['key']; issues.displayProperties.label = - issueProperty['properties']['labels']; - issues.displayProperties.state = issueProperty['properties']['state']; + issueProperty['display_properties']['labels']; + issues.displayProperties.state = issueProperty['display_properties']['state']; issues.displayProperties.subIsseCount = - issueProperty['properties']['sub_issue_count']; + issueProperty['display_properties']['sub_issue_count']; issues.displayProperties.linkCount = - issueProperty['properties']['link']; + issueProperty['display_properties']['link']; issues.displayProperties.attachmentCount = - issueProperty['properties']['attachment_count']; + issueProperty['display_properties']['attachment_count']; issues.displayProperties.priority = - issueProperty['properties']['priority']; + issueProperty['display_properties']['priority']; issues.displayProperties.estimate = - issueProperty['properties']['estimate']; + issueProperty['display_properties']['estimate']; issues.displayProperties.startDate = - issueProperty['properties']['start_date']; + issueProperty['display_properties']['start_date']; issues.displayProperties.createdOn = - issueProperty['properties']['created_on']; + issueProperty['display_properties']['created_on']; issues.displayProperties.updatedOn = - issueProperty['properties']['updated_on']; + issueProperty['display_properties']['updated_on']; } } else { if (issueCategory == IssueCategory.cycleIssues) { cyclesProvider.issueProperty = response.data; issues.displayProperties.assignee = - cyclesProvider.issueProperty['properties']['assignee']; + cyclesProvider.issueProperty['display_properties']['assignee']; cyclesProvider.issues.displayProperties.dueDate = - cyclesProvider.issueProperty['properties']['due_date']; + cyclesProvider.issueProperty['display_properties']['due_date']; cyclesProvider.issues.displayProperties.id = - cyclesProvider.issueProperty['properties']['key']; + cyclesProvider.issueProperty['display_properties']['key']; cyclesProvider.issues.displayProperties.label = - cyclesProvider.issueProperty['properties']['labels']; + cyclesProvider.issueProperty['display_properties']['labels']; cyclesProvider.issues.displayProperties.state = - cyclesProvider.issueProperty['properties']['state']; + cyclesProvider.issueProperty['display_properties']['state']; cyclesProvider.issues.displayProperties.subIsseCount = - cyclesProvider.issueProperty['properties']['sub_issue_count']; + cyclesProvider.issueProperty['display_properties']['sub_issue_count']; cyclesProvider.issues.displayProperties.linkCount = - cyclesProvider.issueProperty['properties']['link']; + cyclesProvider.issueProperty['display_properties']['link']; cyclesProvider.issues.displayProperties.attachmentCount = - cyclesProvider.issueProperty['properties']['attachment_count']; + cyclesProvider.issueProperty['display_properties']['attachment_count']; cyclesProvider.issues.displayProperties.priority = - cyclesProvider.issueProperty['properties']['priority']; + cyclesProvider.issueProperty['display_properties']['priority']; cyclesProvider.issues.displayProperties.estimate = - cyclesProvider.issueProperty['properties']['estimate']; + cyclesProvider.issueProperty['display_properties']['estimate']; cyclesProvider.issues.displayProperties.startDate = - cyclesProvider.issueProperty['properties']['start_date']; + cyclesProvider.issueProperty['display_properties']['start_date']; ref!.read(ProviderList.cyclesProvider).issues.displayProperties = cyclesProvider.issues.displayProperties; } else if (issueCategory == IssueCategory.moduleIssues) { modulesProvider.issueProperty = response.data; issues.displayProperties.assignee = - modulesProvider.issueProperty['properties']['assignee']; + modulesProvider.issueProperty['display_properties']['assignee']; modulesProvider.issues.displayProperties.dueDate = - modulesProvider.issueProperty['properties']['due_date']; + modulesProvider.issueProperty['display_properties']['due_date']; modulesProvider.issues.displayProperties.id = - modulesProvider.issueProperty['properties']['key']; + modulesProvider.issueProperty['display_properties']['key']; issues.displayProperties.label = - issueProperty['properties']['labels']; + issueProperty['display_properties']['labels']; modulesProvider.issues.displayProperties.state = - modulesProvider.issueProperty['properties']['state']; + modulesProvider.issueProperty['display_properties']['state']; modulesProvider.issues.displayProperties.subIsseCount = - modulesProvider.issueProperty['properties']['sub_issue_count']; + modulesProvider.issueProperty['display_properties']['sub_issue_count']; modulesProvider.issues.displayProperties.linkCount = - modulesProvider.issueProperty['properties']['link']; + modulesProvider.issueProperty['display_properties']['link']; modulesProvider.issues.displayProperties.attachmentCount = - modulesProvider.issueProperty['properties']['attachment_count']; + modulesProvider.issueProperty['display_properties']['attachment_count']; modulesProvider.issues.displayProperties.priority = - modulesProvider.issueProperty['properties']['priority']; + modulesProvider.issueProperty['display_properties']['priority']; modulesProvider.issues.displayProperties.estimate = - modulesProvider.issueProperty['properties']['estimate']; + modulesProvider.issueProperty['display_properties']['estimate']; modulesProvider.issues.displayProperties.startDate = - modulesProvider.issueProperty['properties']['start_date']; + modulesProvider.issueProperty['display_properties']['start_date']; modulesProvider.issues.displayProperties.createdOn = - modulesProvider.issueProperty['properties']?['created_on'] ?? + modulesProvider.issueProperty['display_properties']?['created_on'] ?? false; modulesProvider.issues.displayProperties.updatedOn = - modulesProvider.issueProperty['properties']['updated_on']; + modulesProvider.issueProperty['display_properties']['updated_on']; ref!.read(ProviderList.modulesProvider).issues.displayProperties = modulesProvider.issues.displayProperties; } else { issueProperty = response.data; issues.displayProperties.assignee = - issueProperty['properties']['assignee']; + issueProperty['display_properties']['assignee']; issues.displayProperties.dueDate = - issueProperty['properties']['due_date']; - issues.displayProperties.id = issueProperty['properties']['key']; + issueProperty['display_properties']['due_date']; + issues.displayProperties.id = issueProperty['display_properties']['key']; issues.displayProperties.label = - issueProperty['properties']['labels']; - issues.displayProperties.state = issueProperty['properties']['state']; + issueProperty['display_properties']['labels']; + issues.displayProperties.state = issueProperty['display_properties']['state']; issues.displayProperties.subIsseCount = - issueProperty['properties']['sub_issue_count']; + issueProperty['display_properties']['sub_issue_count']; issues.displayProperties.linkCount = - issueProperty['properties']['link']; + issueProperty['display_properties']['link']; issues.displayProperties.attachmentCount = - issueProperty['properties']['attachment_count']; + issueProperty['display_properties']['attachment_count']; issues.displayProperties.priority = - issueProperty['properties']['priority']; + issueProperty['display_properties']['priority']; issues.displayProperties.estimate = - issueProperty['properties']['estimate']; + issueProperty['display_properties']['estimate']; issues.displayProperties.startDate = - issueProperty['properties']['start_date'] ?? false; + issueProperty['display_properties']['start_date'] ?? false; issues.displayProperties.createdOn = - issueProperty['properties']['created_on'] ?? false; + issueProperty['display_properties']['created_on'] ?? false; issues.displayProperties.updatedOn = - issueProperty['properties']['updated_on'] ?? false; + issueProperty['display_properties']['updated_on'] ?? false; // ref!.read(ProviderList.cyclesProvider).issues.displayProperties = issues.displayProperties; } @@ -1337,10 +1301,12 @@ class IssuesProvider extends ChangeNotifier { } void applyIssueView() { + final projectMembers = + ref!.read(ProviderList.projectProvider).projectMembers; final labelIds = labels.map((e) => e['id']).toList(); groupByResponse = IssueFilterHelper.organizeIssues( issuesList, issues.groupBY, issues.orderBY, - labels: labelIds, members: members, states: states); + labels: labelIds, members: projectMembers, states: states); } Future filterIssues({ @@ -1348,17 +1314,19 @@ class IssuesProvider extends ChangeNotifier { required String projID, bool fromViews = false, bool isArchived = false, - String? cycleId, - String? moduleId, Enum issueCategory = IssueCategory.issues, }) async { + final projectProvider = ref!.read(ProviderList.projectProvider); orderByState = StateEnum.loading; notifyListeners(); if (issues.groupBY == GroupBY.labels) { getLabels(slug: slug, projID: projID); } else if (issues.groupBY == GroupBY.createdBY) { - getProjectMembers(slug: slug, projID: projID); + projectProvider.getProjectMembers( + slug: slug, + projId: projID, + ); } else if (issues.groupBY == GroupBY.state) { getStates( slug: slug, @@ -1382,7 +1350,6 @@ class IssuesProvider extends ChangeNotifier { .replaceAll('\$TYPE', Issues.fromIssueType(issues.issueType)); url = '$url${IssueFilterHelper.getFilterQueryParams(issues.filters)}'; url = '$url&sub_issue=${issues.showSubIssues}'; - log('URL: $url'); try { final response = await DioConfig().dioServe( hasAuth: true, @@ -1390,13 +1357,12 @@ class IssuesProvider extends ChangeNotifier { hasBody: false, httpMethod: HttpMethod.get, ); - issuesList = response.data.values.toList(); + issuesList = response.data; final organizedIssues = IssueFilterHelper.organizeIssues( issuesList, issues.groupBY, issues.orderBY, labels: labels.map((e) => e['id']).toList(), - members: members, + members: projectProvider.projectMembers, states: states); - if (issueCategory == IssueCategory.issues) { groupByResponse = organizedIssues; } else if (issueCategory == IssueCategory.cycleIssues || diff --git a/lib/provider/modules_provider.dart b/lib/provider/modules_provider.dart index bec6bf48..b3fa035a 100644 --- a/lib/provider/modules_provider.dart +++ b/lib/provider/modules_provider.dart @@ -16,6 +16,7 @@ import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/global_functions.dart'; +import 'package:plane/utils/issues_filter/issue_filter.helper.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; @@ -70,6 +71,7 @@ class ModuleProvider with ChangeNotifier { List shrinkStates = []; List stateOrdering = []; Map filterIssues = {}; + List moduleIssuesList = []; Map issueProperty = {}; bool showEmptyStates = true; bool isIssuesEmpty = false; @@ -297,7 +299,6 @@ class ModuleProvider with ChangeNotifier { required String moduleId, bool disableLoading = false, }) async { - log('${APIs.listModules.replaceAll('\$SLUG', slug).replaceAll('\$PROJECTID', projId)}$moduleId/'); if (!disableLoading) { moduleDetailState = StateEnum.loading; notifyListeners(); @@ -315,7 +316,6 @@ class ModuleProvider with ChangeNotifier { moduleDetailState = StateEnum.success; currentModule = response.data; notifyListeners(); - log('Module Details ===> ${response.data.toString()}'); } on DioException catch (e) { log(e.error.toString()); moduleDetailState = StateEnum.error; @@ -401,21 +401,63 @@ class ModuleProvider with ChangeNotifier { } } - Future filterModuleIssues({ - required String slug, - required String projectId, - // required Map data, - }) async { + void applyModuleIssuesView({required WidgetRef ref}) { + final issuesProvider = ref.read(ProviderList.issuesProvider); + final labelIds = issuesProvider.labels.map((e) => e['id']).toList(); + final projectProvider = ref.watch(ProviderList.projectProvider); + filterIssues = IssueFilterHelper.organizeIssues( + moduleIssuesList, issues.groupBY, issues.orderBY, + labels: labelIds, + members: projectProvider.projectMembers, + states: issuesProvider.states); + notifyListeners(); + } + + Future filterModuleIssues( + {required String slug, + required String projectId, + String? moduleID, + required WidgetRef ref + // required Map data, + }) async { moduleIssueState = StateEnum.loading; notifyListeners(); - try { - final issuesProvider = ref!.read(ProviderList.issuesProvider); - filterIssues = await issuesProvider.filterIssues( + final issuesProvider = ref.watch(ProviderList.issuesProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + if (issues.groupBY == GroupBY.labels) { + issuesProvider.getLabels(slug: slug, projID: projectId); + } else if (issues.groupBY == GroupBY.createdBY) { + projectProvider.getProjectMembers(slug: slug, projId: projectId); + } else if (issues.groupBY == GroupBY.state) { + issuesProvider.getStates( slug: slug, projID: projectId, - issueCategory: IssueCategory.moduleIssues, + showLoading: false, ); + } + String url; + url = APIs.orderByGroupByModuleIssues + .replaceAll("\$SLUG", slug) + .replaceAll('\$PROJECTID', projectId) + .replaceAll('\$MODULEID', moduleID!) + .replaceAll('\$TYPE', Issues.fromIssueType(issues.issueType)); + url = '$url${IssueFilterHelper.getFilterQueryParams(issues.filters)}'; + url = '$url&sub_issue=${issues.showSubIssues}&show_empty_groups=true'; + try { + final response = await DioConfig().dioServe( + hasAuth: true, + url: url, + hasBody: false, + httpMethod: HttpMethod.get, + ); + moduleIssuesList = response.data.values.toList(); + final organizedIssues = IssueFilterHelper.organizeIssues( + moduleIssuesList, issues.groupBY, issues.orderBY, + labels: issuesProvider.labels.map((e) => e['id']).toList(), + members: projectProvider.projectMembers, + states: issuesProvider.states); + filterIssues = organizedIssues; issuesResponse = []; isIssuesEmpty = true; if (issues.groupBY != GroupBY.none) { @@ -428,7 +470,6 @@ class ModuleProvider with ChangeNotifier { } else { isIssuesEmpty = filterIssues.values.first.isEmpty; } - if (issues.groupBY == GroupBY.state) { issuesProvider.states.forEach((key, value) { if (issues.filters.states.isEmpty && filterIssues[key] == null) { @@ -436,14 +477,13 @@ class ModuleProvider with ChangeNotifier { } shrinkStates.add(false); }); - } else if (issues.groupBY != GroupBY.none) { - stateOrdering = []; + } else { shrinkStates = []; filterIssues.forEach((key, value) { - stateOrdering.add(key); shrinkStates.add(false); }); } + initializeBoard(); moduleIssueState = StateEnum.success; notifyListeners(); @@ -457,18 +497,17 @@ class ModuleProvider with ChangeNotifier { List initializeBoard() { final themeProvider = ref!.read(ProviderList.themeProvider); final issuesProvider = ref!.read(ProviderList.issuesProvider); + final projectProvider = ref!.read(ProviderList.projectProvider); int count = 0; - issuesResponse = []; + // log(issues.groupBY.name); issues.issues = []; + issuesResponse = []; for (int j = 0; j < filterIssues.length; j++) { final List items = []; - - for (int i = 0; - filterIssues[stateOrdering[j]] != null && - i < filterIssues[stateOrdering[j]]!.length; - i++) { - issuesResponse.add(filterIssues[stateOrdering[j]]![i]); - + final groupedIssues = filterIssues.values.toList()[j]; + final groupID = filterIssues.keys.elementAt(j); + for (int i = 0; i < groupedIssues.length; i++) { + issuesResponse.add(groupedIssues[i]); items.add( IssueCardWidget( from: PreviousScreen.modules, @@ -485,32 +524,32 @@ class ModuleProvider with ChangeNotifier { bool userFound = false; for (int i = 0; i < issuesProvider.labels.length; i++) { - if (stateOrdering[j] == issuesProvider.labels[i]['id']) { + if (groupID == issuesProvider.labels[i]['id']) { label = issuesProvider.labels[i]; labelFound = true; break; } } - for (int i = 0; i < issuesProvider.members.length; i++) { - if (stateOrdering[j] == issuesProvider.members[i]['member']['id']) { - userName = issuesProvider.members[i]['member']['first_name'] + + for (int i = 0; i < projectProvider.projectMembers.length; i++) { + if (groupID == projectProvider.projectMembers[i]['member']['id']) { + userName = projectProvider.projectMembers[i]['member']['first_name'] + ' ' + - issuesProvider.members[i]['member']['last_name']; + projectProvider.projectMembers[i]['member']['last_name']; userName = userName.trim().isEmpty - ? issuesProvider.members[i]['member']['email'] + ? projectProvider.projectMembers[i]['member']['email'] : userName; userFound = true; break; } } var title = issues.groupBY == GroupBY.priority - ? stateOrdering[j] + ? groupID : issues.groupBY == GroupBY.state - ? issuesProvider.states[stateOrdering[j]]['name'] - : stateOrdering[j]; + ? issuesProvider.states[groupID]['name'] + : groupID; issues.issues.add(BoardListsData( - id: stateOrdering[j], + id: groupID, items: items, shrink: shrinkStates[j], index: j, @@ -529,7 +568,7 @@ class ModuleProvider with ChangeNotifier { : title = title[0].toString().toUpperCase() + title.toString().substring(1), header: Text( - stateOrdering[j], + groupID, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, @@ -549,6 +588,8 @@ class ModuleProvider with ChangeNotifier { } for (final element in issues.issues) { + // log(issues.groupBY.toString()); + element.leading = issues.groupBY == GroupBY.priority ? element.title == 'Urgent' ? Icon( @@ -602,7 +643,7 @@ class ModuleProvider with ChangeNotifier { element.title.toString().toUpperCase()[0], fontSize: 12, color: Colors.white, - fontWeight: FontWeightt.Semibold, + fontWeight: FontWeightt.Medium, ), ) : issues.groupBY == GroupBY.labels @@ -679,7 +720,7 @@ class ModuleProvider with ChangeNotifier { Const.globalKey.currentContext!, MaterialPageRoute( builder: (ctx) => CreateIssue( - moduleId: currentModule['id'], + cycleId: currentModule['id'], ))); }, child: Icon( @@ -752,7 +793,6 @@ class ModuleProvider with ChangeNotifier { filterIssues[stateOrdering[newListIndex]][newCardIndex]['label_details'] = labelDetails; - log(response.data.toString()); if (issues.groupBY == GroupBY.priority) { log(filterIssues[stateOrdering[newListIndex]][newCardIndex]['name']); filterIssues[stateOrdering[newListIndex]][newCardIndex]['priority'] = @@ -774,7 +814,6 @@ class ModuleProvider with ChangeNotifier { } }); } - log("ISSUE REPOSITIONED"); notifyListeners(); } on DioException catch (err) { (filterIssues[stateOrdering[oldListIndex]] as List).insert(oldCardIndex, diff --git a/lib/provider/my_issues_provider.dart b/lib/provider/my_issues_provider.dart index 1e61c576..5874d609 100644 --- a/lib/provider/my_issues_provider.dart +++ b/lib/provider/my_issues_provider.dart @@ -792,7 +792,6 @@ class MyIssuesProvider extends ChangeNotifier { 'priority': stateOrdering[newListIndex].toString().toLowerCase(), }); - // log(response.data.toString()); if (issues.groupBY == GroupBY.priority) { log(groupByResponse[stateOrdering[newListIndex]][newCardIndex]['name']); groupByResponse[stateOrdering[newListIndex]][newCardIndex]['priority'] = @@ -816,7 +815,6 @@ class MyIssuesProvider extends ChangeNotifier { }); } - log("ISSUE REPOSITIONED"); notifyListeners(); } on DioException catch (err) { (groupByResponse[stateOrdering[oldListIndex]] as List).insert( diff --git a/lib/provider/projects_provider.dart b/lib/provider/projects_provider.dart index b3aba942..4769547b 100644 --- a/lib/provider/projects_provider.dart +++ b/lib/provider/projects_provider.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/kanban/models/project_detail_model.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/config/apis.dart'; import 'package:plane/services/dio_service.dart'; @@ -16,8 +17,8 @@ import 'package:plane/utils/global_functions.dart'; import '../models/issues.dart'; class ProjectsProvider extends ChangeNotifier { - ProjectsProvider(ChangeNotifierProviderRef? this.ref); - final Ref? ref; + ProjectsProvider(ChangeNotifierProviderRef this.ref); + final Ref ref; List projects = []; List starredProjects = []; StateEnum joinprojectState = StateEnum.empty; @@ -91,7 +92,7 @@ class ProjectsProvider extends ChangeNotifier { final viewsProvider = ref.read(ProviderList.viewsProvider.notifier); final intergrationProvider = ref.read(ProviderList.integrationProvider); final workspaceProvider = ref.read(ProviderList.workspaceProvider); - final pageProv = ref.read(ProviderList.pageProvider); + // final pageProv = ref.read(ProviderList.pageProvider); if (currentProject['estimate'] != null && currentProject['estimate'] != '') { // prov.issues.displayProperties.estimate = true; @@ -102,9 +103,9 @@ class ProjectsProvider extends ChangeNotifier { .workspaceSlug; prov.getStates(slug: workspaceSlug, projID: currentProject['id']); - prov.getProjectMembers( + getProjectMembers( slug: workspaceSlug, - projID: currentProject['id'], + projId: currentProject['id'], ); ref.read(ProviderList.estimatesProvider).getEstimates( slug: workspaceSlug, @@ -172,10 +173,10 @@ class ProjectsProvider extends ChangeNotifier { cycleId: '', ref: ref); - pageProv.updatepageList( - slug: workspaceSlug, - projectId: projectID, - ); + // pageProv.updatepageList( + // slug: workspaceSlug, + // projectId: projectID, + // ); if (workspaceProvider.githubIntegration != null) { intergrationProvider.getSlackIntegration( @@ -545,8 +546,10 @@ class ProjectsProvider extends ChangeNotifier { } } - Future getProjectMembers( - {required String slug, required String projId}) async { + Future getProjectMembers({ + required String slug, + required String projId, + }) async { // projectDetailState = AuthStateEnum.loading; // notifyListeners(); try { @@ -558,8 +561,21 @@ class ProjectsProvider extends ChangeNotifier { hasBody: false, httpMethod: HttpMethod.get, ); - projectMembers = response.data; + + for (final element in projectMembers) { + for (final workspace + in ref.watch(ProviderList.workspaceProvider).workspaceMembers) { + if (element['member'] == workspace['member']['id']) { + // Replace the map in projectMembers with the one from workspaceMembers + projectMembers[projectMembers.indexOf(element)] = workspace; + } + if (element["member"] == + ref.read(ProviderList.profileProvider).userProfile.id) { + role = roleParser(role: element["role"]); + } + } + } projectMembersState = StateEnum.success; notifyListeners(); } on DioException catch (e) { diff --git a/lib/screens/MainScreens/Profile/User_profile/over_view.dart b/lib/screens/MainScreens/Profile/User_profile/over_view.dart index a5526873..3636bb90 100644 --- a/lib/screens/MainScreens/Profile/User_profile/over_view.dart +++ b/lib/screens/MainScreens/Profile/User_profile/over_view.dart @@ -6,7 +6,7 @@ import 'package:loading_indicator/loading_indicator.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:plane/config/const.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_active_card.dart b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_active_card.dart index c300cfa0..642f5db5 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_active_card.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_active_card.dart @@ -7,7 +7,7 @@ import 'package:plane/models/chart_model.dart'; import 'package:plane/provider/cycles_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/extensions/list_extensions.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart similarity index 97% rename from lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart index 3a6eb901..5f6cfe3f 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart @@ -94,19 +94,14 @@ class _CycleDetailState extends ConsumerState { stateGroup: [], subscriber: [], ); - issuesProvider.filterIssues( - cycleId: widget.cycleId, - moduleId: widget.moduleId, - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - issueCategory: widget.fromModule - ? IssueCategory.moduleIssues - : IssueCategory.cycleIssues, - projID: widget.projId ?? - ref.read(ProviderList.projectProvider).currentProject['id']); - widget.fromModule ? getModuleData() : getCycleData(); + + WidgetsBinding.instance.addPostFrameCallback((_) async { + if (widget.fromModule) { + getModuleData(); + } else { + getCycleData(); + } + }); super.initState(); } @@ -130,18 +125,18 @@ class _CycleDetailState extends ConsumerState { disableLoading: true) .then((value) => getChartData(modulesProvider .moduleDetailsData['distribution']['completion_chart'])); - issuesProvider.getIssueDisplayProperties( issueCategory: IssueCategory.moduleIssues); - modulesProvider .filterModuleIssues( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: ref.read(ProviderList.projectProvider).currentProject['id'], - ) + moduleID: widget.moduleId, + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: + ref.read(ProviderList.projectProvider).currentProject['id'], + ref: ref) .then((value) { if (modulesProvider.issues.projectView == ProjectView.list) { modulesProvider.initializeBoard(); @@ -175,16 +170,18 @@ class _CycleDetailState extends ConsumerState { ref .read(ProviderList.issuesProvider) .getIssueDisplayProperties(issueCategory: IssueCategory.cycleIssues); + await cyclesProvider + .getCycleView(cycleId: widget.cycleId!); cyclesProvider .filterCycleIssues( - cycleID: widget.cycleId!, - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: widget.projId ?? - ref.read(ProviderList.projectProvider).currentProject['id'], - ) + cycleID: widget.cycleId!, + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: widget.projId ?? + ref.read(ProviderList.projectProvider).currentProject['id'], + ref: ref) .then((value) { if (issuesProvider.issues.projectView == ProjectView.list) { cyclesProvider.initializeBoard(); @@ -281,6 +278,11 @@ class _CycleDetailState extends ConsumerState { Navigator.pop(context); return; } + if (widget.fromModule) { + modulesProvider.changeTabIndex(0); + } else { + cyclesProvider.changeTabIndex(0); + } modulesProvider.selectedIssues = []; cyclesProvider.selectedIssues = []; issueProvider.issues.projectView = issueProvider.tempProjectView; @@ -1016,6 +1018,10 @@ class _CycleDetailState extends ConsumerState { .moduleIssues : IssueCategory .cycleIssues, + cycleOrModuleId: + widget.fromModule + ? widget.moduleId + : widget.cycleId, ); }); }, @@ -1046,21 +1052,13 @@ class _CycleDetailState extends ConsumerState { ), ], ), - widget.fromModule - ? Container( - color: themeProvider.themeManager - .secondaryBackgroundDefaultColor, - padding: - const EdgeInsets.only(left: 25, right: 25), - child: activeCycleDetails(fromModule: true), - ) - : Container( - color: themeProvider.themeManager - .secondaryBackgroundDefaultColor, - padding: - const EdgeInsets.only(left: 25, right: 25), - child: activeCycleDetails(), - ), + // Container( + // color: themeProvider + // .themeManager.secondaryBackgroundDefaultColor, + // padding: const EdgeInsets.only(left: 25, right: 25), + // child: activeCycleDetails( + // fromModule: widget.fromModule ? true : false), + // ), ], ), ), @@ -1075,9 +1073,8 @@ class _CycleDetailState extends ConsumerState { final cyclesProvider = ref.watch(ProviderList.cyclesProvider); final modulesProvider = ref.watch(ProviderList.modulesProvider); - if (widget.fromModule - ? modulesProvider.moduleDetailState == StateEnum.loading - : cyclesProvider.cyclesDetailState == StateEnum.loading) { + if (modulesProvider.moduleDetailState == StateEnum.loading || + cyclesProvider.cyclesDetailState == StateEnum.loading) { return Center( child: SizedBox( width: 30, @@ -1106,7 +1103,7 @@ class _CycleDetailState extends ConsumerState { const SizedBox(height: 30), labelsPart(fromModule: widget.fromModule), const SizedBox(height: 30), - widget.fromModule ? links() : Container() + // widget.fromModule ? links() : Container() ], ); } @@ -1801,7 +1798,7 @@ class _CycleDetailState extends ConsumerState { color: themeProvider.themeManager.primaryTextColor, )), const SizedBox(height: 10), - detailData['distribution']['assignees'].length == 0 + detailData['assignees'].length == 0 ? const CustomText('No data found.') : Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), @@ -1816,7 +1813,7 @@ class _CycleDetailState extends ConsumerState { child: Column( children: [ ...List.generate( - detailData['distribution']['assignees'].length, + detailData['assignees'].length, (idx) { return Container( padding: const EdgeInsets.symmetric( @@ -1824,8 +1821,8 @@ class _CycleDetailState extends ConsumerState { margin: const EdgeInsets.symmetric(vertical: 2), decoration: BoxDecoration( color: (issuesProvider.issues.filters.assignees - .contains(detailData['distribution'] - ['assignees'][idx]['assignee_id']) + .contains(detailData['assignees'][idx] + ['assignee_id']) ? themeProvider.themeManager .secondaryBackgroundDefaultColor : themeProvider.themeManager @@ -1839,19 +1836,16 @@ class _CycleDetailState extends ConsumerState { children: [ Padding( padding: const EdgeInsets.only(right: 10), - child: detailData['distribution'] - ['assignees'][idx] + child: detailData['assignees'][idx] ['avatar'] != null && - detailData['distribution'] - ['assignees'][idx] + detailData['assignees'][idx] ['avatar'] != '' ? CircleAvatar( radius: 10, backgroundImage: NetworkImage( - detailData['distribution'] - ['assignees'][idx] + detailData['assignees'][idx] ['avatar']), ) : CircleAvatar( @@ -1861,14 +1855,10 @@ class _CycleDetailState extends ConsumerState { .tertiaryBackgroundDefaultColor, child: Center( child: CustomText( - detailData['distribution'][ - 'assignees'] - [idx] + detailData['assignees'][idx] ['first_name'] != null - ? detailData['distribution'] - [ - 'assignees'] + ? detailData['assignees'] [idx] ['first_name'][0] .toString() @@ -1879,7 +1869,7 @@ class _CycleDetailState extends ConsumerState { ), )), CustomText( - detailData['distribution']['assignees'][idx] + detailData['assignees'][idx] ['display_name'] ?? 'No Assignees', color: themeProvider @@ -1888,10 +1878,10 @@ class _CycleDetailState extends ConsumerState { ], ), CompletionPercentage( - value: detailData['distribution']['assignees'] - [idx]['completed_issues'], - totalValue: detailData['distribution'] - ['assignees'][idx]['total_issues']) + value: detailData['assignees'][idx] + ['completed_issues'], + totalValue: detailData['assignees'][idx] + ['total_issues']) ], ), ); diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/project_details_cycles.dart b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/project_details_cycles.dart index aa6263ee..4b97c6ff 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/project_details_cycles.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/project_details_cycles.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_active_card.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart index b327dbbb..e5c58483 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart @@ -79,7 +79,7 @@ class _CreateIssueState extends ConsumerState tempStatesIcons = prov.stateIcons; tempLabels = prov.labels; tempIssues = ref.read(ProviderList.searchIssueProvider).issues; - tempAssignees = prov.members; + tempAssignees = projectProvider.projectMembers; if (widget.fromMyIssues) { prov.statesState = StateEnum.loading; @@ -174,14 +174,13 @@ class _CreateIssueState extends ConsumerState } return WillPopScope( onWillPop: () async { - log('WillPopScope'); issuesProvider.createIssuedata = {}; issuesProvider.statesData = tempStatesData; issuesProvider.states = tempStates; issuesProvider.stateOrdering = tempStateOrdering; issuesProvider.stateIcons = tempStatesIcons; issuesProvider.labels = tempLabels; - issuesProvider.members = tempAssignees; + projectProvider.projectMembers = tempAssignees; issuesProvider.setsState(); ref.read(ProviderList.searchIssueProvider).issues = tempIssues; ref.read(ProviderList.issueProvider).clearCookies(); @@ -200,7 +199,7 @@ class _CreateIssueState extends ConsumerState issuesProvider.stateOrdering = tempStateOrdering; issuesProvider.stateIcons = tempStatesIcons; issuesProvider.labels = tempLabels; - issuesProvider.members = tempAssignees; + projectProvider.projectMembers = tempAssignees; issuesProvider.setsState(); ref.read(ProviderList.issueProvider).clearCookies(); ref.read(ProviderList.searchIssueProvider).issues = tempIssues; @@ -1840,7 +1839,7 @@ class _CreateIssueState extends ConsumerState issuesProvider.stateOrdering = tempStateOrdering; issuesProvider.stateIcons = tempStatesIcons; issuesProvider.labels = tempLabels; - issuesProvider.members = tempAssignees; + projectProvider.projectMembers = tempAssignees; issuesProvider.setsState(); ref.read(ProviderList.searchIssueProvider).issues = tempIssues; @@ -1877,7 +1876,7 @@ class _CreateIssueState extends ConsumerState tempIssues = ref .read(ProviderList.searchIssueProvider) .issues; - tempAssignees = issuesProvider.members; + tempAssignees = projectProvider.projectMembers; if (widget.fromMyIssues) { issuesProvider diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart index 5111f379..24ab7597 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart @@ -117,12 +117,12 @@ class _IssueDetailState extends ConsumerState { case PreviousScreen.cycles: reff .read(ProviderList.cyclesProvider) - .filterCycleIssues(slug: workspaceSlug, projectId: projID); + .filterCycleIssues(slug: workspaceSlug, projectId: projID, ref: ref); break; case PreviousScreen.modules: reff .read(ProviderList.modulesProvider) - .filterModuleIssues(slug: workspaceSlug, projectId: projID); + .filterModuleIssues(slug: workspaceSlug, projectId: projID, ref: ref); break; case PreviousScreen.views: reff diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_card.dart b/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_card.dart index a202f97f..600bfc22 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_card.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_card.dart @@ -4,7 +4,7 @@ import 'package:intl/intl.dart'; import 'package:plane/bottom_sheets/delete_module_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/utils/constants.dart'; import '/utils/enums.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/simple_module_card.dart b/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/simple_module_card.dart index d971510a..089a19b3 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/simple_module_card.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/simple_module_card.dart @@ -7,7 +7,7 @@ import 'package:plane/utils/string_manager.dart'; import '/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/widgets/custom_text.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; class SimpleModuleCard extends ConsumerStatefulWidget { const SimpleModuleCard({ diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart index d6053d10..9e4154c2 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; @@ -67,14 +65,6 @@ class _ProjectDetailState extends ConsumerState { //issueProvider.statesState = StateEnum.restricted; }); - // pages = [ - // cycles(), - // cycles(), - // const ModuleScreen(), - // const Views(), - // //const PageScreen() - // ]; - super.initState(); } diff --git a/lib/startup/dependency_resolver.dart b/lib/startup/dependency_resolver.dart index 677f7cdd..334be556 100644 --- a/lib/startup/dependency_resolver.dart +++ b/lib/startup/dependency_resolver.dart @@ -19,7 +19,7 @@ import '../utils/theme_manager.dart'; class DependencyResolver { static Future resolve({required WidgetRef ref}) async { - await _resolveConfig(ref).then((_) async { + // await _resolveConfig(ref).then((_) async { if (Const.accessToken == null) { CustomToast(manager: ThemeManager(THEME.light)); FlutterNativeSplash.remove(); @@ -68,7 +68,7 @@ class DependencyResolver { _resolveNotifications(ref); _resolveWhatsNew(ref); FlutterNativeSplash.remove(); - }); + // }); } static Future _resolveConfig(WidgetRef ref) async { diff --git a/lib/utils/issues_filter/group_by_issues.dart b/lib/utils/issues_filter/group_by_issues.dart index 64d2cc6f..7705219e 100644 --- a/lib/utils/issues_filter/group_by_issues.dart +++ b/lib/utils/issues_filter/group_by_issues.dart @@ -1,3 +1,4 @@ + import 'package:plane/utils/enums.dart'; class IssuesGroupBYHelper { @@ -19,10 +20,11 @@ class IssuesGroupBYHelper { stateGroups[state]! .sort((a, b) => a['sequence'].compareTo(b['sequence'])); } + for (final stateGroup in stateGroups.keys) { for (final state in stateGroups[stateGroup]!) { groupedIssues[state['id']] = - issues.where((issue) => issue['state'] == state['id']).toList(); + issues.where((issue) => issue['state_id'] == state['id']).toList(); } } return groupedIssues; diff --git a/lib/widgets/issue_card_widget.dart b/lib/widgets/issue_card_widget.dart index b0908b1f..d9f0f7ad 100644 --- a/lib/widgets/issue_card_widget.dart +++ b/lib/widgets/issue_card_widget.dart @@ -1,8 +1,11 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:intl/intl.dart'; import 'package:plane/config/const.dart'; +import 'package:plane/provider/projects_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; @@ -198,16 +201,17 @@ class _IssueCardWidgetState extends ConsumerState { ? Container( margin: const EdgeInsets.only(top: 15), child: CustomRichText( - type: FontStyle.Small, - color: themeProvider.themeManager.placeholderTextColor, - widgets: [ - TextSpan( - text: provider.issuesResponse[widget.cardIndex] - ['project_detail']['identifier']), - TextSpan( - text: - '-${provider.issuesResponse[widget.cardIndex]['sequence_id']}'), - ])) + type: FontStyle.Small, + color: themeProvider.themeManager.placeholderTextColor, + widgets: [ + TextSpan( + text: projectProvider.currentProject['identifier']), + TextSpan( + text: + '-${provider.issuesResponse[widget.cardIndex]['sequence_id']}'), + ], + ), + ) : Container(), const SizedBox( height: 10, @@ -329,156 +333,116 @@ class _IssueCardWidgetState extends ConsumerState { width: 0, ), (provider.issues.displayProperties.label == true && - provider.issuesResponse[widget.cardIndex] - ['label_details'] != - null && provider - .issuesResponse[widget.cardIndex] - ['label_details'] + .issuesResponse[widget.cardIndex]['label_ids'] .isNotEmpty) - ? SizedBox( - height: 30, - child: provider - .issuesResponse[widget.cardIndex] - ['label_details'] - .length > - 1 - ? Container( - width: 80, - margin: const EdgeInsets.only(right: 5), - padding: const EdgeInsets.only( - left: 8, - right: 8, - ), - decoration: BoxDecoration( - border: Border.all( - color: themeProvider - .themeManager.borderSubtle01Color, - ), - borderRadius: BorderRadius.circular(4)), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: [ - CircleAvatar( - radius: 5, - backgroundColor: provider - .issuesResponse[widget.cardIndex] - ['label_details'][0]['color'] - .toString() - .toColor(), - ), - const SizedBox( - width: 5, - ), - CustomText( - '${provider.issuesResponse[widget.cardIndex]['label_details'].length} Labels', - type: FontStyle.XSmall, - height: 1, - color: themeProvider - .themeManager.tertiaryTextColor, - ), - ], - ), - ) - : Container( - margin: const EdgeInsets.only(right: 5), - child: ListView.builder( - padding: EdgeInsets.zero, - scrollDirection: Axis.horizontal, - physics: - const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: provider - .issuesResponse[widget.cardIndex] - ['label_details'] - .length, - itemBuilder: (context, idx) { - return Container( - height: 30, - padding: const EdgeInsets.only( - left: 8, - right: 8, - ), - decoration: BoxDecoration( - border: Border.all( - color: themeProvider - .themeManager - .borderSubtle01Color), - borderRadius: - BorderRadius.circular(4)), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: [ - CircleAvatar( - radius: 5, - backgroundColor: provider - .issuesResponse[ - widget.cardIndex] - ['label_details'][idx] - ['color'] - .toString() - .toColor(), - ), - const SizedBox( - width: 5, - ), - Container( - constraints: - const BoxConstraints( - maxWidth: 120), - child: CustomText( - provider.issuesResponse[ - widget.cardIndex] - ['label_details'][idx] - ['name'], - type: FontStyle.XSmall, - overflow: - TextOverflow.ellipsis, - maxLines: 1, - height: 1, - color: themeProvider - .themeManager - .tertiaryTextColor, - ), - ), - ], - ), - ); - }, - ), - ), - ) - : (provider.issues.displayProperties.label == true && - provider - .issuesResponse[widget.cardIndex] - ['label_details'] - .isEmpty) + ? provider.issuesResponse[widget.cardIndex]['label_ids'] + .length == + 1 ? Container( - height: 30, + width: 80, margin: const EdgeInsets.only(right: 5), - alignment: Alignment.center, padding: const EdgeInsets.only( left: 8, right: 8, ), decoration: BoxDecoration( border: Border.all( - color: themeProvider - .themeManager.borderSubtle01Color), + color: themeProvider + .themeManager.borderSubtle01Color, + ), borderRadius: BorderRadius.circular(4)), - child: CustomText( - 'No Label', - type: FontStyle.XSmall, - height: 1, - color: themeProvider - .themeManager.tertiaryTextColor, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + CircleAvatar( + radius: 5, + backgroundColor: getLabelDetail( + provider.issuesResponse[ + widget.cardIndex] + ['label_ids'][0])['color'] + .toString() + .toColor(), + ), + const SizedBox( + width: 5, + ), + CustomText( + '${provider.issuesResponse[widget.cardIndex]['label_ids'].length} Labels', + type: FontStyle.XSmall, + height: 1, + color: themeProvider + .themeManager.tertiaryTextColor, + ), + ], ), ) : Container( - width: 0, - ), + margin: const EdgeInsets.only(right: 5), + child: ListView.builder( + padding: EdgeInsets.zero, + scrollDirection: Axis.horizontal, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: provider + .issuesResponse[widget.cardIndex] + ['label_ids'] + .length, + itemBuilder: (context, idx) { + return Container( + height: 30, + padding: const EdgeInsets.only( + left: 8, + right: 8, + ), + decoration: BoxDecoration( + border: Border.all( + color: themeProvider.themeManager + .borderSubtle01Color), + borderRadius: + BorderRadius.circular(4)), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + CircleAvatar( + radius: 5, + backgroundColor: getLabelDetail( + provider.issuesResponse[ + widget + .cardIndex] + ['label_details'] + [idx])['color'] + .toString() + .toColor(), + ), + const SizedBox( + width: 5, + ), + Container( + constraints: const BoxConstraints( + maxWidth: 120), + child: CustomText( + getLabelDetail( + provider.issuesResponse[ + widget.cardIndex] + ['label_details'] + [idx])['name'], + type: FontStyle.XSmall, + overflow: TextOverflow.ellipsis, + maxLines: 1, + height: 1, + color: themeProvider.themeManager + .tertiaryTextColor, + ), + ), + ], + ), + ); + }, + ), + ) + : Container(), provider.issues.displayProperties.dueDate == true ? Container( height: 30, @@ -903,4 +867,15 @@ class _IssueCardWidgetState extends ConsumerState { ), ); } + + Map getLabelDetail(String issueId) { + final issuesProvider = ref.watch(ProviderList.issuesProvider); + Map? issueDetail; + for (final label in issuesProvider.labels) { + if (issueId == label['id']) { + log(issueId); + } + } + return issueDetail!; + } } From 3436f09032547d01bda7604bc4d19c819b4ca71c Mon Sep 17 00:00:00 2001 From: LAKHAN BAHETI Date: Tue, 16 Jan 2024 17:33:12 +0530 Subject: [PATCH 3/7] refactor: project detail --- lib/bottom_sheets/type_sheet.dart | 68 +- lib/bottom_sheets/views_and_layout_sheet.dart | 14 +- lib/bottom_sheets/views_sheet.dart | 34 +- lib/models/issues.dart | 4 +- lib/provider/cycles_provider.dart | 20 +- lib/provider/issues_provider.dart | 24 +- lib/provider/modules_provider.dart | 2 +- lib/provider/my_issues_provider.dart | 20 +- .../My_issues/my_issues_screen.dart | 6 +- .../CyclesTab/cycle_module_detail.dart | 18 +- .../Kanban Layout/kanban_root.dart | 74 ++ .../Issue Layouts/List Layout/list_root.dart | 130 ++ .../Issue Layouts/issue_layout.dart | 40 + .../ProjectDetail/IssuesTab/issues_tab.dart | 30 + .../ProjectDetail/ViewsTab/views_detail.dart | 6 +- .../ProjectDetail/archived_issues.dart | 8 +- .../models/project_detail_models.dart | 10 + .../ProjectDetail/project_detail.dart | 1090 +---------------- .../widgets/floating_action_button.dart | 106 ++ .../widgets/project_detail_appbar.dart | 65 + .../project_detail_bottom_actions.dart | 293 +++++ .../widgets/project_detail_root.dart | 94 ++ .../widgets/project_detail_tabs.dart | 69 ++ lib/utils/enums.dart | 2 +- lib/widgets/issue_card_widget.dart | 18 +- 25 files changed, 1077 insertions(+), 1168 deletions(-) create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/Kanban Layout/kanban_root.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/issue_layout.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart diff --git a/lib/bottom_sheets/type_sheet.dart b/lib/bottom_sheets/type_sheet.dart index 33ded9ec..6e042a5a 100644 --- a/lib/bottom_sheets/type_sheet.dart +++ b/lib/bottom_sheets/type_sheet.dart @@ -20,11 +20,11 @@ class _TypeSheetState extends ConsumerState { final dynamic prov = widget.issueCategory == IssueCategory.myIssues ? ref.read(ProviderList.myIssuesProvider) : ref.read(ProviderList.issuesProvider); - selected = prov.issues.projectView == ProjectView.kanban + selected = prov.issues.projectView == IssueLayout.kanban ? 0 - : prov.issues.projectView == ProjectView.list + : prov.issues.projectView == IssueLayout.list ? 1 - : prov.issues.projectView == ProjectView.calendar + : prov.issues.projectView == IssueLayout.calendar ? 2 : 3; super.initState(); @@ -80,13 +80,13 @@ class _TypeSheetState extends ConsumerState { .workspaceSlug; if (widget.issueCategory == IssueCategory.myIssues) { - myIssuesProv.issues.projectView = ProjectView.kanban; + myIssuesProv.issues.projectView = IssueLayout.kanban; myIssuesProv.setState(); myIssuesProv.updateMyIssueView(); } else { - prov.issues.projectView = ProjectView.kanban; + prov.issues.projectView = IssueLayout.kanban; if (widget.issueCategory == IssueCategory.issues) { - prov.tempProjectView = ProjectView.kanban; + prov.tempProjectView = IssueLayout.kanban; } if (prov.issues.groupBY == GroupBY.none) { prov.issues.groupBY = GroupBY.state; @@ -108,7 +108,7 @@ class _TypeSheetState extends ConsumerState { prov.filterIssues(slug: worspaceSlug, projID: projID); } } - // prov.tempProjectView = ProjectView.kanban; + // prov.tempProjectView = IssueLayout.kanban; prov.setsState(); if (widget.issueCategory == IssueCategory.issues) { prov.updateProjectView(); @@ -137,12 +137,12 @@ class _TypeSheetState extends ConsumerState { if (widget.issueCategory == IssueCategory.myIssues) { myIssuesProv.issues.projectView = - ProjectView.kanban; + IssueLayout.kanban; myIssuesProv.setState(); myIssuesProv.updateMyIssueView(); } else { - prov.issues.projectView = ProjectView.kanban; - prov.tempProjectView = ProjectView.kanban; + prov.issues.projectView = IssueLayout.kanban; + prov.tempProjectView = IssueLayout.kanban; prov.setsState(); if (widget.issueCategory == IssueCategory.issues) { @@ -174,13 +174,13 @@ class _TypeSheetState extends ConsumerState { child: InkWell( onTap: () { if (widget.issueCategory == IssueCategory.myIssues) { - myIssuesProv.issues.projectView = ProjectView.list; + myIssuesProv.issues.projectView = IssueLayout.list; myIssuesProv.setState(); myIssuesProv.updateMyIssueView(); } else { - prov.issues.projectView = ProjectView.list; + prov.issues.projectView = IssueLayout.list; if (widget.issueCategory == IssueCategory.issues) { - prov.tempProjectView = ProjectView.list; + prov.tempProjectView = IssueLayout.list; } prov.setsState(); @@ -211,12 +211,12 @@ class _TypeSheetState extends ConsumerState { if (widget.issueCategory == IssueCategory.myIssues) { myIssuesProv.issues.projectView = - ProjectView.list; + IssueLayout.list; myIssuesProv.setState(); myIssuesProv.updateMyIssueView(); } else { - prov.issues.projectView = ProjectView.list; - prov.tempProjectView = ProjectView.list; + prov.issues.projectView = IssueLayout.list; + prov.tempProjectView = IssueLayout.list; prov.setsState(); if (widget.issueCategory == IssueCategory.issues) { @@ -252,10 +252,10 @@ class _TypeSheetState extends ConsumerState { width: double.infinity, child: InkWell( onTap: () { - prov.issues.projectView = ProjectView.calendar; + prov.issues.projectView = IssueLayout.calendar; if (widget.issueCategory == IssueCategory.issues) { - prov.tempProjectView = ProjectView.calendar; + prov.tempProjectView = IssueLayout.calendar; } prov.setsState(); @@ -285,8 +285,8 @@ class _TypeSheetState extends ConsumerState { value: 2, onChanged: (val) { prov.issues.projectView = - ProjectView.calendar; - prov.tempProjectView = ProjectView.calendar; + IssueLayout.calendar; + prov.tempProjectView = IssueLayout.calendar; prov.setsState(); if (widget.issueCategory == @@ -322,10 +322,10 @@ class _TypeSheetState extends ConsumerState { width: double.infinity, child: InkWell( onTap: () { - prov.issues.projectView = ProjectView.spreadsheet; + prov.issues.projectView = IssueLayout.spreadsheet; if (widget.issueCategory == IssueCategory.issues) { - prov.tempProjectView = ProjectView.spreadsheet; + prov.tempProjectView = IssueLayout.spreadsheet; } prov.setsState(); @@ -355,9 +355,9 @@ class _TypeSheetState extends ConsumerState { value: 3, onChanged: (val) { prov.issues.projectView = - ProjectView.spreadsheet; + IssueLayout.spreadsheet; prov.tempProjectView = - ProjectView.spreadsheet; + IssueLayout.spreadsheet; prov.setsState(); if (widget.issueCategory == @@ -388,25 +388,25 @@ class _TypeSheetState extends ConsumerState { // ontap: () { // if (widget.issueCategory == IssueCategory.myIssues) { // if (selected == 0) { - // myIssuesProv.issues.projectView = ProjectView.kanban; + // myIssuesProv.issues.projectView = IssueLayout.kanban; // } else if (selected == 1) { - // myIssuesProv.issues.projectView = ProjectView.list; + // myIssuesProv.issues.projectView = IssueLayout.list; // } // myIssuesProv.setState(); // myIssuesProv.updateMyIssueView(); // } else { // if (selected == 0) { - // prov.issues.projectView = ProjectView.kanban; - // prov.tempProjectView = ProjectView.kanban; + // prov.issues.projectView = IssueLayout.kanban; + // prov.tempProjectView = IssueLayout.kanban; // } else if (selected == 1) { - // prov.issues.projectView = ProjectView.list; - // prov.tempProjectView = ProjectView.list; + // prov.issues.projectView = IssueLayout.list; + // prov.tempProjectView = IssueLayout.list; // } else if (selected == 2) { - // prov.issues.projectView = ProjectView.calendar; - // prov.tempProjectView = ProjectView.calendar; + // prov.issues.projectView = IssueLayout.calendar; + // prov.tempProjectView = IssueLayout.calendar; // } else if (selected == 3) { - // prov.issues.projectView = ProjectView.spreadsheet; - // prov.tempProjectView = ProjectView.spreadsheet; + // prov.issues.projectView = IssueLayout.spreadsheet; + // prov.tempProjectView = IssueLayout.spreadsheet; // } // prov.setsState(); // if (widget.issueCategory == IssueCategory.issues) { diff --git a/lib/bottom_sheets/views_and_layout_sheet.dart b/lib/bottom_sheets/views_and_layout_sheet.dart index efa2f32e..40fbc7c5 100644 --- a/lib/bottom_sheets/views_and_layout_sheet.dart +++ b/lib/bottom_sheets/views_and_layout_sheet.dart @@ -141,11 +141,11 @@ class _ViewsAndLayoutSheetState extends ConsumerState { final dynamic prov = widget.issueCategory == IssueCategory.myIssues ? ref.read(ProviderList.myIssuesProvider) : ref.read(ProviderList.issuesProvider); - selected = prov.issues.projectView == ProjectView.kanban + selected = prov.issues.projectView == IssueLayout.kanban ? 0 - : prov.issues.projectView == ProjectView.list + : prov.issues.projectView == IssueLayout.list ? 1 - : prov.issues.projectView == ProjectView.calendar + : prov.issues.projectView == IssueLayout.calendar ? 2 : 3; @@ -298,7 +298,7 @@ class _ViewsAndLayoutSheetState extends ConsumerState { child: InkWell( onTap: () { myIssuesProvider.issues.projectView = - ProjectView.list; + IssueLayout.list; myIssuesProvider.setState(); myIssuesProvider.updateMyIssueView(); Navigator.of(context).pop(); @@ -340,7 +340,7 @@ class _ViewsAndLayoutSheetState extends ConsumerState { child: InkWell( onTap: () { myIssuesProvider.issues.projectView = - ProjectView.kanban; + IssueLayout.kanban; myIssuesProvider.setState(); myIssuesProvider.updateMyIssueView(); Navigator.of(context).pop(); @@ -636,7 +636,7 @@ class _ViewsAndLayoutSheetState extends ConsumerState { .themeManager.primaryColour), myIssuesProvider.issues.projectView == - ProjectView.list + IssueLayout.list ? RadioListTile( fillColor: groupBy == 'none' ? null @@ -980,7 +980,7 @@ class _ViewsAndLayoutSheetState extends ConsumerState { tag['name'] != 'ID' && tag['name'] != 'Assignee') && myIssuesProvider.issues.projectView == - ProjectView.list) + IssueLayout.list) ? const SizedBox() : GestureDetector( onTap: () { diff --git a/lib/bottom_sheets/views_sheet.dart b/lib/bottom_sheets/views_sheet.dart index d127fa89..fd46ee53 100644 --- a/lib/bottom_sheets/views_sheet.dart +++ b/lib/bottom_sheets/views_sheet.dart @@ -21,7 +21,7 @@ class ViewsSheet extends ConsumerStatefulWidget { super.key, }); final Enum issueCategory; - final ProjectView projectView; + final IssueLayout projectView; final bool fromView; final String? cycleId; final bool isArchived; @@ -173,12 +173,12 @@ class _ViewsSheetState extends ConsumerState { Column( children: [ const SizedBox(height: 10), - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? const SizedBox( height: 40, ) : Container(), - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? CustomExpansionTile( title: 'Group by', child: Wrap( @@ -377,7 +377,7 @@ class _ViewsSheetState extends ConsumerState { ListTileControlAffinity.leading, activeColor: themeProvider .themeManager.primaryColour), - widget.projectView == ProjectView.list + widget.projectView == IssueLayout.list ? RadioListTile( fillColor: groupBy == 'none' ? null @@ -415,12 +415,12 @@ class _ViewsSheetState extends ConsumerState { ], ), - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? customHorizontalLine() : Container(), //expansion tile for order by having two checkboxes last created and last updated - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? CustomExpansionTile( title: 'Order by', child: Wrap( @@ -560,12 +560,12 @@ class _ViewsSheetState extends ConsumerState { ) : Container(), - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? customHorizontalLine() : Container(), //expansion tile for issue type having three checkboxes all issues, active issues and backlog issues - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? CustomExpansionTile( title: 'Issue type', child: Wrap( @@ -650,11 +650,11 @@ class _ViewsSheetState extends ConsumerState { ) : Container(), - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? customHorizontalLine() : Container(), - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? InkWell( onTap: () { setState(() { @@ -703,10 +703,10 @@ class _ViewsSheetState extends ConsumerState { ) : Container(), - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? customHorizontalLine() : Container(), - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? InkWell( onTap: () { setState(() { @@ -754,13 +754,13 @@ class _ViewsSheetState extends ConsumerState { ), ) : Container(), - issueProvider.issues.projectView != ProjectView.spreadsheet + issueProvider.issues.projectView != IssueLayout.spreadsheet ? Container( height: 20, ) : Container(), - issueProvider.issues.projectView == ProjectView.spreadsheet + issueProvider.issues.projectView == IssueLayout.spreadsheet ? Container( height: 45, ) @@ -873,18 +873,18 @@ class _ViewsSheetState extends ConsumerState { : (((tag['name'] == 'Created on' || tag['name'] == 'Updated on') && issueProvider.issues.projectView != - ProjectView.spreadsheet) || + IssueLayout.spreadsheet) || ((tag['name'] == 'ID' || tag['name'] == 'Attachment Count' || tag['name'] == 'Link' || tag['name'] == 'Sub Issue Count') && issueProvider.issues.projectView == - ProjectView.spreadsheet) || + IssueLayout.spreadsheet) || ((tag['name'] != 'Priority' && tag['name'] != 'ID' && tag['name'] != 'Assignee') && issueProvider.issues.projectView == - ProjectView.list)) + IssueLayout.list)) ? const SizedBox() : GestureDetector( onTap: () { diff --git a/lib/models/issues.dart b/lib/models/issues.dart index 58056122..8807b863 100644 --- a/lib/models/issues.dart +++ b/lib/models/issues.dart @@ -61,7 +61,7 @@ class Issues { required this.showSubIssues, required this.displayProperties}); List issues = []; - ProjectView projectView; + IssueLayout projectView; GroupBY groupBY = GroupBY.state; OrderBY orderBY = OrderBY.manual; bool showSubIssues = true; @@ -84,7 +84,7 @@ class Issues { return Issues( issues: [], showSubIssues: true, - projectView: ProjectView.kanban, + projectView: IssueLayout.kanban, groupBY: GroupBY.state, orderBY: OrderBY.lastCreated, issueType: IssueType.all, diff --git a/lib/provider/cycles_provider.dart b/lib/provider/cycles_provider.dart index ec1df444..02ebb782 100644 --- a/lib/provider/cycles_provider.dart +++ b/lib/provider/cycles_provider.dart @@ -444,7 +444,7 @@ class CyclesProvider with ChangeNotifier { items: items, shrink: shrinkStates[j], index: j, - width: issuesProvider.issues.projectView == ProjectView.list + width: issuesProvider.issues.projectView == IssueLayout.list ? MediaQuery.of(Const.globalKey.currentContext!).size.width : 300, // shrink: shrinkissuesProvider.states[count++], @@ -831,12 +831,12 @@ class CyclesProvider with ChangeNotifier { log(response.toString()); cycleView = response.data; issues.projectView = cycleView['display_filters']['layout'] == 'list' - ? ProjectView.list + ? IssueLayout.list : cycleView['display_filters']['layout'] == 'calendar' - ? ProjectView.calendar + ? IssueLayout.calendar : cycleView['display_filters']['layout'] == 'spreadsheet' - ? ProjectView.spreadsheet - : ProjectView.kanban; + ? IssueLayout.spreadsheet + : IssueLayout.kanban; issues.showSubIssues = cycleView['display_filters']['sub_issue'] ?? true; issues.groupBY = Issues.toGroupBY(cycleView["display_filters"]["group_by"]); @@ -859,7 +859,7 @@ class CyclesProvider with ChangeNotifier { showEmptyStates = cycleView["display_filters"]["show_empty_groups"]; if (issues.groupBY == GroupBY.none) { - issues.projectView = ProjectView.list; + issues.projectView = IssueLayout.list; } if (reset) { updateCycleView(); @@ -868,7 +868,7 @@ class CyclesProvider with ChangeNotifier { notifyListeners(); } on DioException catch (e) { log(e.response.toString()); - issues.projectView = ProjectView.kanban; + issues.projectView = IssueLayout.kanban; cycleViewState = StateEnum.error; notifyListeners(); } @@ -1001,11 +1001,11 @@ class CyclesProvider with ChangeNotifier { "type": Issues.fromIssueType(issues.issueType), "show_empty_groups": showEmptyStates, if (!isArchive) - "layout": issues.projectView == ProjectView.kanban + "layout": issues.projectView == IssueLayout.kanban ? 'kanban' - : issues.projectView == ProjectView.list + : issues.projectView == IssueLayout.list ? 'list' - : issues.projectView == ProjectView.calendar + : issues.projectView == IssueLayout.calendar ? 'calendar' : 'spreadsheet', "sub_issue": false, diff --git a/lib/provider/issues_provider.dart b/lib/provider/issues_provider.dart index 1ebc8a0b..7168ac61 100644 --- a/lib/provider/issues_provider.dart +++ b/lib/provider/issues_provider.dart @@ -53,7 +53,7 @@ class IssuesProvider extends ChangeNotifier { subscriber: [], ); IssueType tempIssueType = IssueType.all; - ProjectView tempProjectView = ProjectView.kanban; + IssueLayout tempProjectView = IssueLayout.kanban; OrderBY tempOrderBy = OrderBY.lastCreated; Map stateIcons = {}; Map issueProperty = {}; @@ -145,7 +145,7 @@ class IssuesProvider extends ChangeNotifier { showEmptyStates = true; issues = Issues( issues: [], - projectView: ProjectView.kanban, + projectView: IssueLayout.kanban, groupBY: GroupBY.state, orderBY: OrderBY.manual, showSubIssues: true, @@ -272,7 +272,7 @@ class IssuesProvider extends ChangeNotifier { items: items, shrink: j >= shrinkStates.length ? false : shrinkStates[j], index: j, - width: issues.projectView == ProjectView.list + width: issues.projectView == IssueLayout.list ? MediaQuery.of(Const.globalKey.currentContext!).size.width : (width > 500 ? 400 : width * 0.8), // shrink: shrinkStates[count++], @@ -1195,11 +1195,11 @@ class IssuesProvider extends ChangeNotifier { "type": Issues.fromIssueType(issues.issueType), "show_empty_groups": showEmptyStates, if (!isArchive) - "layout": issues.projectView == ProjectView.kanban + "layout": issues.projectView == IssueLayout.kanban ? 'kanban' - : issues.projectView == ProjectView.list + : issues.projectView == IssueLayout.list ? 'list' - : issues.projectView == ProjectView.calendar + : issues.projectView == IssueLayout.calendar ? 'calendar' : 'spreadsheet', "sub_issue": false, @@ -1257,12 +1257,12 @@ class IssuesProvider extends ChangeNotifier { issueView = reset ? response.data["default_props"] : response.data["view_props"]; issues.projectView = issueView['display_filters']['layout'] == 'list' - ? ProjectView.list + ? IssueLayout.list : issueView['display_filters']['layout'] == 'calendar' - ? ProjectView.calendar + ? IssueLayout.calendar : issueView['display_filters']['layout'] == 'spreadsheet' - ? ProjectView.spreadsheet - : ProjectView.kanban; + ? IssueLayout.spreadsheet + : IssueLayout.kanban; issues.showSubIssues = issueView['display_filters']['sub_issue'] ?? true; issues.groupBY = Issues.toGroupBY(issueView["display_filters"]["group_by"]); @@ -1285,7 +1285,7 @@ class IssuesProvider extends ChangeNotifier { showEmptyStates = issueView["display_filters"]["show_empty_groups"]; if (issues.groupBY == GroupBY.none) { - issues.projectView = ProjectView.list; + issues.projectView = IssueLayout.list; } if (reset) { updateProjectView(); @@ -1294,7 +1294,7 @@ class IssuesProvider extends ChangeNotifier { notifyListeners(); } on DioException catch (e) { log(e.response.toString()); - issues.projectView = ProjectView.kanban; + issues.projectView = IssueLayout.kanban; projectViewState = StateEnum.error; notifyListeners(); } diff --git a/lib/provider/modules_provider.dart b/lib/provider/modules_provider.dart index b3fa035a..63e3f1b5 100644 --- a/lib/provider/modules_provider.dart +++ b/lib/provider/modules_provider.dart @@ -553,7 +553,7 @@ class ModuleProvider with ChangeNotifier { items: items, shrink: shrinkStates[j], index: j, - width: issuesProvider.issues.projectView == ProjectView.list + width: issuesProvider.issues.projectView == IssueLayout.list ? MediaQuery.of(Const.globalKey.currentContext!).size.width : 300, // shrink: shrinkissuesProvider.states[count++], diff --git a/lib/provider/my_issues_provider.dart b/lib/provider/my_issues_provider.dart index 5874d609..761a8488 100644 --- a/lib/provider/my_issues_provider.dart +++ b/lib/provider/my_issues_provider.dart @@ -73,7 +73,7 @@ class MyIssuesProvider extends ChangeNotifier { issues = Issues( showSubIssues: true, issues: [], - projectView: ProjectView.kanban, + projectView: IssueLayout.kanban, groupBY: GroupBY.state, orderBY: OrderBY.manual, issueType: IssueType.all, @@ -141,12 +141,12 @@ class MyIssuesProvider extends ChangeNotifier { ); myIssueView = response.data["view_props"]; issues.projectView = myIssueView["display_filters"]['layout'] == 'list' - ? ProjectView.list + ? IssueLayout.list : myIssueView["display_filters"]['layout'] == 'calendar' - ? ProjectView.calendar + ? IssueLayout.calendar : myIssueView["display_filters"]['layout'] == 'spreadsheet' - ? ProjectView.spreadsheet - : ProjectView.kanban; + ? IssueLayout.spreadsheet + : IssueLayout.kanban; issues.groupBY = Issues.toGroupBY(myIssueView["display_filters"]['group_by']); issues.orderBY = @@ -195,7 +195,7 @@ class MyIssuesProvider extends ChangeNotifier { notifyListeners(); } on DioException catch (e) { log("MY ISSUES:${e.response}"); - issues.projectView = ProjectView.kanban; + issues.projectView = IssueLayout.kanban; myIssuesViewState = StateEnum.error; notifyListeners(); } @@ -519,7 +519,7 @@ class MyIssuesProvider extends ChangeNotifier { items: items, shrink: j >= shrinkStates.length ? false : shrinkStates[j], index: j, - width: issues.projectView == ProjectView.list + width: issues.projectView == IssueLayout.list ? MediaQuery.of(Const.globalKey.currentContext!).size.width : (width > 500 ? 400 : width * 0.8), // shrink: shrinkStates[count++], @@ -860,11 +860,11 @@ class MyIssuesProvider extends ChangeNotifier { "start_date": issues.filters.startDate, }, "display_filters": { - "layout": issues.projectView == ProjectView.kanban + "layout": issues.projectView == IssueLayout.kanban ? 'kanban' - : issues.projectView == ProjectView.list + : issues.projectView == IssueLayout.list ? 'list' - : issues.projectView == ProjectView.calendar + : issues.projectView == IssueLayout.calendar ? 'calendar' : 'spreadsheet', "group_by": Issues.fromGroupBY(issues.groupBY), diff --git a/lib/screens/MainScreens/My_issues/my_issues_screen.dart b/lib/screens/MainScreens/My_issues/my_issues_screen.dart index c416d48f..48cc3d83 100644 --- a/lib/screens/MainScreens/My_issues/my_issues_screen.dart +++ b/lib/screens/MainScreens/My_issues/my_issues_screen.dart @@ -446,7 +446,7 @@ class _MyIssuesScreenState extends ConsumerState { final projectProvider = ref.watch(ProviderList.projectProvider); final profileProvider = ref.watch(ProviderList.profileProvider); // log(issueProvider.issueState.name); - if (issueProvider.issues.projectView == ProjectView.list) { + if (issueProvider.issues.projectView == IssueLayout.list) { issueProvider.initializeBoard(); } @@ -455,7 +455,7 @@ class _MyIssuesScreenState extends ConsumerState { issueProvider.myIssuesFilterState == StateEnum.loading, widgetClass: Container( color: themeProvider.themeManager.secondaryBackgroundDefaultColor, - padding: issueProvider.issues.projectView == ProjectView.kanban + padding: issueProvider.issues.projectView == IssueLayout.kanban ? const EdgeInsets.only(top: 15, left: 0) : null, child: issueProvider.myIssuesViewState == StateEnum.loading @@ -484,7 +484,7 @@ class _MyIssuesScreenState extends ConsumerState { ), ], ) - : issueProvider.issues.projectView == ProjectView.list + : issueProvider.issues.projectView == IssueLayout.list ? Container( color: themeProvider .themeManager.secondaryBackgroundDefaultColor, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart index 5f6cfe3f..b5e408ef 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart @@ -77,7 +77,7 @@ class _CycleDetailState extends ConsumerState { issuesProvider.tempIssueType = issuesProvider.issues.issueType; issuesProvider.tempFilters = issuesProvider.issues.filters; - issuesProvider.issues.projectView = ProjectView.kanban; + issuesProvider.issues.projectView = IssueLayout.kanban; issuesProvider.issues.groupBY = GroupBY.state; issuesProvider.issues.orderBY = OrderBY.lastCreated; @@ -138,7 +138,7 @@ class _CycleDetailState extends ConsumerState { ref.read(ProviderList.projectProvider).currentProject['id'], ref: ref) .then((value) { - if (modulesProvider.issues.projectView == ProjectView.list) { + if (modulesProvider.issues.projectView == IssueLayout.list) { modulesProvider.initializeBoard(); } }); @@ -183,7 +183,7 @@ class _CycleDetailState extends ConsumerState { ref.read(ProviderList.projectProvider).currentProject['id'], ref: ref) .then((value) { - if (issuesProvider.issues.projectView == ProjectView.list) { + if (issuesProvider.issues.projectView == IssueLayout.list) { cyclesProvider.initializeBoard(); } }); @@ -547,10 +547,10 @@ class _CycleDetailState extends ConsumerState { projectId: widget.projId, type: IssueCategory.cycleIssues, ref: ref) - : ((!widget.fromModule && issueProvider.issues.projectView == ProjectView.list) || + : ((!widget.fromModule && issueProvider.issues.projectView == IssueLayout.list) || (widget.fromModule && issueProvider.issues.projectView == - ProjectView.list)) + IssueLayout.list)) ? Container( color: themeProvider .themeManager @@ -674,10 +674,10 @@ class _CycleDetailState extends ConsumerState { .toList()), ), ) - : ((!widget.fromModule && issueProvider.issues.projectView == ProjectView.kanban) || + : ((!widget.fromModule && issueProvider.issues.projectView == IssueLayout.kanban) || (widget.fromModule && issueProvider.issues.projectView == - ProjectView.kanban)) + IssueLayout.kanban)) ? Padding( padding: const EdgeInsets.only( @@ -803,7 +803,7 @@ class _CycleDetailState extends ConsumerState { .w500), ), ) - : ((!widget.fromModule && issueProvider.issues.projectView == ProjectView.calendar) || (widget.fromModule && issueProvider.issues.projectView == ProjectView.calendar)) + : ((!widget.fromModule && issueProvider.issues.projectView == IssueLayout.calendar) || (widget.fromModule && issueProvider.issues.projectView == IssueLayout.calendar)) ? const CalendarView() : SpreadSheetView( issueCategory: @@ -926,7 +926,7 @@ class _CycleDetailState extends ConsumerState { .themeManager.borderSubtle01Color, ), issueProvider.issues.projectView == - ProjectView.calendar + IssueLayout.calendar ? Container() : Expanded( child: GestureDetector( diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/Kanban Layout/kanban_root.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/Kanban Layout/kanban_root.dart new file mode 100644 index 00000000..b7f1077b --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/Kanban Layout/kanban_root.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/kanban/custom/board.dart'; +import 'package:plane/kanban/models/inputs.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/utils/custom_toast.dart'; +import 'package:plane/utils/enums.dart'; + +class KanbanLayoutRoot extends ConsumerStatefulWidget { + const KanbanLayoutRoot({required this.isViews, super.key}); + final bool isViews; + @override + ConsumerState createState() => _KanbanLayoutRootState(); +} + +class _KanbanLayoutRootState extends ConsumerState { + @override + Widget build(BuildContext context) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final issuesProvider = ref.watch(ProviderList.issuesProvider); + return KanbanBoard( + issuesProvider.initializeBoard(views: widget.isViews), + boardID: 'issues-board', + isCardsDraggable: issuesProvider.checkIsCardsDaraggable(), + onItemReorder: ( + {newCardIndex, newListIndex, oldCardIndex, oldListIndex}) { + // print('newCardIndex: $newCardIndex, newListIndex: $newListIndex, oldCardIndex: $oldCardIndex, oldListIndex: $oldListIndex'); + issuesProvider + .reorderIssue( + context: context, + newCardIndex: newCardIndex!, + newListIndex: newListIndex!, + oldCardIndex: oldCardIndex!, + oldListIndex: oldListIndex!, + ) + .then((value) { + if (issuesProvider.issues.orderBY != OrderBY.manual) { + CustomToast.showToast(context, + message: + 'This board is ordered by ${issuesProvider.issues.orderBY == OrderBY.lastUpdated ? 'last updated' : 'created at'} ', + toastType: ToastType.warning); + } + }).catchError((e) { + CustomToast.showToast(context, + message: 'Failed to update issue', toastType: ToastType.failure); + }); + }, + groupEmptyStates: !issuesProvider.showEmptyStates, + backgroundColor: + themeProvider.themeManager.secondaryBackgroundDefaultColor, + cardPlaceHolderColor: + themeProvider.themeManager.primaryBackgroundDefaultColor, + cardPlaceHolderDecoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + boxShadow: [ + BoxShadow( + blurRadius: 2, + color: themeProvider.themeManager.borderSubtle01Color, + spreadRadius: 0, + ), + ]), + listScrollConfig: ScrollConfig( + offset: 65, + duration: const Duration(milliseconds: 100), + curve: Curves.linear), + boardScrollConfig: ScrollConfig( + offset: 45, + duration: const Duration(milliseconds: 100), + curve: Curves.linear), + listTransitionDuration: const Duration(milliseconds: 200), + cardTransitionDuration: const Duration(milliseconds: 400), + ); + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart new file mode 100644 index 00000000..8e0f76d7 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/custom_text.dart'; + +class ListLayoutRoot extends ConsumerStatefulWidget { + const ListLayoutRoot({super.key}); + + @override + ConsumerState createState() => _ListLayoutRootState(); +} + +class _ListLayoutRootState extends ConsumerState { + @override + Widget build(BuildContext context) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final issuesProvider = ref.watch(ProviderList.issuesProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + return Container( + color: themeProvider.themeManager.secondaryBackgroundDefaultColor, + margin: const EdgeInsets.only(top: 5), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: issuesProvider.issues.issues + .map((state) => state.items.isEmpty && + !issuesProvider.showEmptyStates + ? Container() + : SizedBox( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.only(left: 15), + margin: const EdgeInsets.only(bottom: 10), + child: Row( + children: [ + state.leading ?? Container(), + Container( + padding: const EdgeInsets.only( + left: 10, + ), + width: + MediaQuery.of(context).size.width * 0.6, + child: CustomText( + state.title!, + overflow: TextOverflow.ellipsis, + maxLines: 1, + type: FontStyle.Large, + color: themeProvider + .themeManager.primaryTextColor, + fontWeight: FontWeightt.Semibold, + ), + ), + Container( + alignment: Alignment.center, + margin: const EdgeInsets.only( + left: 15, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: themeProvider.themeManager + .tertiaryBackgroundDefaultColor), + height: 25, + width: 30, + child: CustomText( + state.items.length.toString(), + type: FontStyle.Small, + ), + ), + const Spacer(), + projectProvider.role == Role.admin || + projectProvider.role == Role.member + ? IconButton( + onPressed: () { + if (issuesProvider.issues.groupBY == + GroupBY.state) { + issuesProvider.createIssuedata[ + 'state'] = state.id; + } + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => + const CreateIssue())); + }, + icon: Icon( + Icons.add, + color: themeProvider + .themeManager.tertiaryTextColor, + )) + : Container( + height: 40, + ), + const SizedBox( + width: 10, + ), + ], + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: state.items.map((e) => e).toList()), + state.items.isEmpty + ? Container( + margin: const EdgeInsets.only(bottom: 10), + width: MediaQuery.of(context).size.width, + color: themeProvider.themeManager + .primaryBackgroundDefaultColor, + padding: const EdgeInsets.only( + top: 15, bottom: 15, left: 15), + child: const CustomText( + 'No issues.', + type: FontStyle.Small, + maxLines: 10, + textAlign: TextAlign.start, + ), + ) + : Container( + margin: const EdgeInsets.only(bottom: 10), + ) + ], + ), + )) + .toList()), + ), + ); + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/issue_layout.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/issue_layout.dart new file mode 100644 index 00000000..5b82c8f1 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/issue_layout.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issue%20Layouts/Kanban%20Layout/kanban_root.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issue%20Layouts/List%20Layout/list_root.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/calender_view.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/empty.dart'; + +class IssueLayoutHandler extends ConsumerStatefulWidget { + const IssueLayoutHandler( + {required this.issueLayout, required this.isView, super.key}); + final IssueLayout issueLayout; + final bool isView; + @override + ConsumerState createState() => _IssueLayoutState(); +} + +class _IssueLayoutState extends ConsumerState { + @override + Widget build(BuildContext context) { + final issueProvider = ref.watch(ProviderList.issuesProvider); + + return issueProvider.groupByResponse.isEmpty && + issueProvider.issueState == StateEnum.success + ? EmptyPlaceholder.emptyIssues(context, ref: ref) + : widget.issueLayout == IssueLayout.list + ? const ListLayoutRoot() + : widget.issueLayout == IssueLayout.kanban + ? KanbanLayoutRoot( + isViews: widget.isView, + ) + : widget.issueLayout == IssueLayout.calendar + ? const CalendarView() + : const SpreadSheetView( + issueCategory: IssueCategory.issues, + ); + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart new file mode 100644 index 00000000..e40857f3 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issue%20Layouts/issue_layout.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/loading_widget.dart'; + +class IssuesTab extends ConsumerStatefulWidget { + const IssuesTab({super.key}); + + @override + ConsumerState createState() => _IssuesTabState(); +} + +class _IssuesTabState extends ConsumerState { + @override + Widget build(BuildContext context) { + final issueProvider = ref.watch(ProviderList.issuesProvider); + return LoadingWidget( + loading: issueProvider.issuePropertyState == StateEnum.loading || + issueProvider.issueState == StateEnum.loading || + issueProvider.statesState == StateEnum.loading || + issueProvider.projectViewState == StateEnum.loading || + issueProvider.orderByState == StateEnum.loading, + widgetClass: IssueLayoutHandler( + issueLayout: issueProvider.issues.projectView, + isView: false, + )); + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart index aabef5ed..ce26f33d 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart @@ -5,7 +5,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/project_detail.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/loading_widget.dart'; @@ -64,7 +63,7 @@ class _ViewsDetailState extends ConsumerState { issuesProvider.tempIssueType = issuesProvider.issues.issueType; issuesProvider.tempFilters = issuesProvider.issues.filters; - issuesProvider.issues.projectView = ProjectView.kanban; + issuesProvider.issues.projectView = IssueLayout.kanban; issuesProvider.issues.groupBY = GroupBY.state; issuesProvider.issues.orderBY = OrderBY.lastCreated; @@ -330,7 +329,8 @@ class _ViewsDetailState extends ConsumerState { color: themeProvider.themeManager.borderSubtle01Color, width: double.infinity, ), - Expanded(child: issues(context, ref, isViews: true)), + // TODO: Add views here + // Expanded(child: issues(context, ref, isViews: true)), SafeArea( child: Container( height: 50, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart b/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart index 8a275778..ca14e26c 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart @@ -25,7 +25,7 @@ class _ArchivedIssuesState extends ConsumerState { super.initState(); final issueProvider = ref.read(ProviderList.issuesProvider); issueProvider.tempProjectView = issueProvider.issues.projectView; - issueProvider.issues.projectView = ProjectView.list; + issueProvider.issues.projectView = IssueLayout.list; issueProvider.setsState(); issueProvider.filterIssues( @@ -44,7 +44,7 @@ class _ArchivedIssuesState extends ConsumerState { final issueProvider = ref.watch(ProviderList.issuesProvider); final projectProvider = ref.watch(ProviderList.projectProvider); // log(issueProvider.issueState.name); - if (issueProvider.issues.projectView == ProjectView.list) { + if (issueProvider.issues.projectView == IssueLayout.list) { issueProvider.initializeBoard( isArchive: true, ); @@ -315,7 +315,7 @@ class _ArchivedIssuesState extends ConsumerState { .borderSubtle01Color, ), issueProvider.issues.projectView == - ProjectView.calendar + IssueLayout.calendar ? Container() : Expanded( child: InkWell( @@ -350,7 +350,7 @@ class _ArchivedIssuesState extends ConsumerState { .issues, isArchived: true, projectView: - ProjectView + IssueLayout .list, ); }); diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart b/lib/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart new file mode 100644 index 00000000..63cc45a1 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart @@ -0,0 +1,10 @@ +class ProjectDetailTab { + ProjectDetailTab({ + required this.title, + required this.width, + required this.show, + }); + String title; + double width; + bool show; +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart index 9e4154c2..379ce7df 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart @@ -1,34 +1,14 @@ +// ignore_for_file: non_constant_identifier_names import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; -import 'package:plane/bottom_sheets/page_filter_sheet.dart'; -import 'package:plane/bottom_sheets/type_sheet.dart'; -import 'package:plane/bottom_sheets/views_sheet.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/calender_view.dart'; -import 'package:plane/kanban/custom/board.dart'; -// import 'package:google_fonts/google_fonts.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/project_details_cycles.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_screen.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart'; -import 'package:plane/screens/MainScreens/Projects/create_page_screen.dart'; -import 'package:plane/screens/settings_screen.dart'; -import 'package:plane/utils/constants.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart'; import 'package:plane/utils/enums.dart'; -import 'package:plane/widgets/custom_app_bar.dart'; -import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/empty.dart'; -import 'package:plane/widgets/error_state.dart'; -import 'package:plane/widgets/loading_widget.dart'; - -import '../../../../kanban/models/inputs.dart'; -import '../../../../utils/custom_toast.dart'; -import '../../../create_view_screen.dart'; -import 'CyclesTab/create_cycle.dart'; -import 'ModulesTab/create_module.dart'; +import 'widgets/project_detail_appbar.dart'; +import 'widgets/project_detail_root.dart'; class ProjectDetail extends ConsumerStatefulWidget { const ProjectDetail({super.key, required this.index}); @@ -39,18 +19,29 @@ class ProjectDetail extends ConsumerStatefulWidget { } class _ProjectDetailState extends ConsumerState { - // final tabs = [ - // {'title': 'Issues', 'width': 60}, - // {'title': 'Cycles', 'width': 60}, - // {'title': 'Modules', 'width': 75}, - // {'title': 'Views', 'width': 60}, - // {'title': 'Pages', 'width': 50}, - // ]; final controller = PageController(initialPage: 0); + int selectedTab = 0; + + void onTabChange(int index) { + setState(() { + selectedTab = index; + }); + } - int selected = 0; - List pages = []; - int numberOfTabs = 0; + void settingsOntap() { + final projectProvider = ref.read(ProviderList.projectProvider); + int count = 0; + for (int i = 0; i < projectProvider.features.length; i++) { + if (projectProvider.features[i]['show']) { + count++; + } + } + if (count < selectedTab + 1) { + setState(() { + selectedTab = count - 1; + }); + } + } @override void initState() { @@ -60,1023 +51,43 @@ class _ProjectDetailState extends ConsumerState { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { issueProvider.setsState(); issueProvider.statesState = StateEnum.restricted; - ref.read(ProviderList.projectProvider).initializeProject(ref: ref); - //issueProvider.statesState = StateEnum.restricted; }); super.initState(); } - void setPages() { - final projectProvider = ref.watch(ProviderList.projectProvider); - - pages = [ - { - 'title': 'Issues', - 'width': 60, - 'show': true, - 'page': issues(context, ref) - }, - ]; - if (projectProvider.features[1]['show'] == true) { - pages.add( - {'title': 'Cycles', 'width': 60, 'show': true, 'page': cycles()}); - } - if (projectProvider.features[2]['show'] == true) { - pages.add({ - 'title': 'Modules', - 'width': 75, - 'show': true, - 'page': const ModuleScreen() - }); - } - if (projectProvider.features[3]['show'] == true) { - pages.add( - {'title': 'Views', 'width': 60, 'show': true, 'page': const Views()}); - } - } - @override Widget build(BuildContext context) { - final themeProvider = ref.watch(ProviderList.themeProvider); final issueProvider = ref.watch(ProviderList.issuesProvider); final projectProvider = ref.watch(ProviderList.projectProvider); - final cycleProvider = ref.watch(ProviderList.cyclesProvider); - final moduleProvider = ref.watch(ProviderList.modulesProvider); - final viewsProvider = ref.watch(ProviderList.viewsProvider); - final pageProvider = ref.watch(ProviderList.pageProvider); - - setPages(); - - // log(issueProvider.issues.groupBY.name); return Scaffold( - appBar: CustomAppBar( - elevation: false, - onPressed: () { - Navigator.pop(context); - }, - text: ref.read(ProviderList.projectProvider).currentProject['name'], - actions: [ - (projectProvider.currentProject['archive_in'] > 0 && - (projectProvider.role == Role.admin || - projectProvider.role == Role.member) && - (issueProvider.statesState == StateEnum.success)) - ? IconButton( - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (ctx) => const ArchivedIssues(), - ), - ); - }, - icon: Icon( - Icons.archive_outlined, - color: themeProvider.themeManager.placeholderTextColor, - )) - : Container(), - (issueProvider.statesState == StateEnum.success) - ? IconButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const SettingScreen(), - ), - ).then((value) { - int count = 0; - for (int i = 0; - i < projectProvider.features.length; - i++) { - if (projectProvider.features[i]['show']) { - count++; - } - } - if (count < selected + 1) { - setState(() { - selected = count - 1; - }); - } - }); - }, - icon: issueProvider.statesState == StateEnum.restricted - ? Container() - : Icon( - Icons.settings_outlined, - color: - themeProvider.themeManager.placeholderTextColor, - ), - ) - : Container(), - ], + appBar: ProjectDetailAppbar( + context, + ref: ref, + settingsOntap: settingsOntap, ), - floatingActionButton: selected != 0 && - (projectProvider.role == Role.admin || - projectProvider.role == Role.member) && - ((selected == 1 && cycleProvider.showAddFloatingButton()) || - (selected == 2 && - moduleProvider.moduleState != StateEnum.loading && - (moduleProvider.modules.isNotEmpty || - moduleProvider.favModules.isNotEmpty)) || - (selected == 3 && - viewsProvider.viewsState != StateEnum.loading && - viewsProvider.views.isNotEmpty)) - ? FloatingActionButton( - backgroundColor: themeProvider.themeManager.primaryColour, - child: Icon( - Icons.add, - color: themeProvider.themeManager.textonColor, - ), - onPressed: () { - if (selected == 1 && projectProvider.features[1]['show']) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (ctx) => const CreateCycle(), - ), - ); - } - - if (selected == 1 && - !projectProvider.features[1]['show'] && - projectProvider.features[2]['show']) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (ctx) => const CreateModule(), - ), - ); - } - - if (selected == 1 && - !projectProvider.features[1]['show'] && - !projectProvider.features[2]['show']) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (ctx) => const CreateView(), - ), - ); - } - - if (selected == 2 && - projectProvider.features[2]['show'] && - projectProvider.features[1]['show']) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (ctx) => const CreateModule(), - ), - ); - } - - if ((selected == 2 && - projectProvider.features[2]['show'] && - !projectProvider.features[1]['show']) || - (selected == 2 && - !projectProvider.features[2]['show'] && - projectProvider.features[1]['show'])) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (ctx) => const CreateView(), - ), - ); - } - if (selected == 3) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (ctx) => const CreateView(), - ), - ); - } - // if (selected == 4) { - // Navigator.of(context).push( - // MaterialPageRoute( - // builder: (ctx) => const CreatePage(), - // ), - // ); - // } - }, - ) - : Container(), + floatingActionButton: + FLActionButton(context, ref: ref, selected: selectedTab), body: SafeArea( - child: issueProvider.statesState == StateEnum.restricted - ? EmptyPlaceholder.joinProject( - context, - ref, - projectProvider.currentProject['id'], - ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug) - : Container( - // color: themeProvider.backgroundColor, - color: themeProvider.themeManager.primaryBackgroundDefaultColor, - child: projectProvider.projectDetailState == StateEnum.error - ? errorState( - context: context, - ontap: () { - ref - .read(ProviderList.projectProvider) - .initializeProject(ref: ref); - }) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - issueProvider.statesState != StateEnum.loading - ? Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: pages.map((e) { - return e['show'] - ? Expanded( - child: InkWell( - onTap: () { - controller.jumpToPage( - pages.indexOf(e)); - setState(() { - selected = pages.indexOf(e); - }); - }, - child: Column( - children: [ - Container( - margin: const EdgeInsets - .symmetric(vertical: 8), - child: CustomText( - e['title'].toString(), - color: pages.indexOf(e) == - selected - ? themeProvider - .themeManager - .primaryColour - : themeProvider - .themeManager - .placeholderTextColor, - overrride: true, - type: FontStyle.Medium, - fontWeight: pages - .indexOf(e) == - selected - ? FontWeightt.Medium - : null, - ), - ), - selected == - pages - .indexOf(e) && - (pages.elementAt(pages - .indexOf( - e))[ - 'show'] == - true || - projectProvider - .features - .elementAt( - pages.indexOf( - e))['show'] == - true) - ? Container( - height: 6, - decoration: - BoxDecoration( - borderRadius: - BorderRadius - .circular( - 10), - color: themeProvider - .themeManager - .primaryColour, - ), - ) - : Container( - height: 6, - ) - ], - ), - ), - ) - : Container(); - }).toList(), - ) - : Container(), - Container( - height: 2, - width: MediaQuery.of(context).size.width, - color: - themeProvider.themeManager.borderSubtle01Color, - ), - Expanded( - child: PageView.builder( - controller: controller, - onPageChanged: (page) { - setState(() { - selected = page; - }); - }, - itemBuilder: (ctx, index) { - return Container( - child: index == 0 - ? issues(ctx, ref) - : pages[index]['page']); - }, - itemCount: pages.length, - ), - ), - issueProvider.statesState == StateEnum.loading || - issueProvider.issueState == StateEnum.loading - ? Container() - : selected == 0 && - issueProvider.statesState == - StateEnum.restricted - ? Container() - : selected == 0 && - issueProvider.statesState == - StateEnum.success - ? Container( - decoration: BoxDecoration( - color: themeProvider.themeManager - .primaryBackgroundDefaultColor, - boxShadow: themeProvider - .themeManager - .shadowBottomControlButtons, - ), - height: 50, - width: - MediaQuery.of(context).size.width, - child: Row( - children: [ - projectProvider.role == - Role.admin || - projectProvider.role == - Role.member - ? Expanded( - child: InkWell( - onTap: () { - issueProvider - .createIssuedata[ - 'state'] = - issueProvider - .states - .keys - .first; - - Navigator.of(context) - .push( - MaterialPageRoute( - builder: (context) => - const CreateIssue(), - ), - ); - }, - child: SizedBox.expand( - child: Row( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Icon( - Icons.add, - color: themeProvider - .themeManager - .primaryTextColor, - size: 20, - ), - const CustomText( - ' Issue', - type: FontStyle - .Medium, - ) - ], - ), - ), - ), - ) - : Container(), - Container( - height: 50, - width: 0.5, - color: themeProvider - .themeManager - .borderSubtle01Color, - ), - Expanded( - child: InkWell( - onTap: () { - showModalBottomSheet( - isScrollControlled: true, - enableDrag: true, - constraints: - BoxConstraints( - maxHeight: - height * 0.5), - shape: - const RoundedRectangleBorder( - borderRadius: - BorderRadius - .only( - topLeft: - Radius.circular(30), - topRight: - Radius.circular(30), - )), - context: context, - builder: (ctx) { - return const TypeSheet( - issueCategory: - IssueCategory - .issues, - ); - }); - }, - child: SizedBox.expand( - child: Row( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Icon( - Icons.list_outlined, - color: themeProvider - .themeManager - .primaryTextColor, - size: 19, - ), - const CustomText( - ' Layout', - type: FontStyle.Medium, - ) - ], - ), - ), - )), - Container( - height: 50, - width: 0.5, - color: themeProvider - .themeManager - .borderSubtle01Color, - ), - issueProvider - .issues.projectView == - ProjectView.calendar - ? Container() - : Expanded( - child: InkWell( - onTap: () { - showModalBottomSheet( - isScrollControlled: - true, - enableDrag: true, - constraints: BoxConstraints( - maxHeight: MediaQuery.of( - context) - .size - .height * - 0.9), - shape: - const RoundedRectangleBorder( - borderRadius: - BorderRadius - .only( - topLeft: Radius - .circular(30), - topRight: Radius - .circular(30), - )), - context: context, - builder: (ctx) { - return ViewsSheet( - projectView: - issueProvider - .issues - .projectView, - issueCategory: - IssueCategory - .issues, - ); - }); - }, - child: SizedBox.expand( - child: Row( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Icon( - Icons - .wysiwyg_outlined, - color: themeProvider - .themeManager - .primaryTextColor, - size: 19, - ), - const CustomText( - ' Display', - type: FontStyle - .Medium, - ) - ], - ), - ), - )), - Container( - height: 50, - width: 0.5, - color: themeProvider - .themeManager - .borderSubtle01Color, - ), - Expanded( - child: InkWell( - onTap: () { - showModalBottomSheet( - isScrollControlled: true, - enableDrag: true, - constraints: BoxConstraints( - minHeight: - MediaQuery.of( - context) - .size - .height * - 0.75, - maxHeight: - MediaQuery.of( - context) - .size - .height * - 0.85), - shape: - const RoundedRectangleBorder( - borderRadius: - BorderRadius - .only( - topLeft: - Radius.circular(30), - topRight: - Radius.circular(30), - )), - context: context, - builder: (ctx) { - return FilterSheet( - issueCategory: - IssueCategory - .issues, - ); - }); - }, - child: SizedBox.expand( - child: Row( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Icon( - Icons - .filter_list_outlined, - color: themeProvider - .themeManager - .primaryTextColor, - size: 19, - ), - const CustomText( - ' Filters', - type: FontStyle.Medium, - ) - ], - ), - ), - )), - ], - ), - ) - : Container(), - selected == 4 - ? selected == 4 && - pageProvider - .pages[pageProvider.selectedFilter]! - .isEmpty - ? Container() - : Container( - height: 51, - width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - color: themeProvider.themeManager - .primaryBackgroundDefaultColor, - boxShadow: themeProvider.themeManager - .shadowBottomControlButtons, - ), - child: Column( - children: [ - SizedBox( - height: 50, - child: Row( - children: [ - projectProvider.role == - Role.admin - ? Expanded( - child: InkWell( - onTap: () { - Navigator.of( - context) - .push( - MaterialPageRoute( - builder: - (context) => - const CreatePage(), - ), - ); - }, - child: - SizedBox.expand( - child: Row( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Icon( - Icons.add, - color: themeProvider - .themeManager - .primaryTextColor, - size: 20, - ), - const CustomText( - ' Page', - type: FontStyle - .Medium, - ) - ], - ), - ), - ), - ) - : Container(), - Container( - height: 50, - width: 0.5, - color: themeProvider - .themeManager - .borderSubtle01Color, - ), - Expanded( - child: InkWell( - onTap: () { - showModalBottomSheet( - isScrollControlled: - true, - enableDrag: true, - constraints: BoxConstraints( - maxHeight: MediaQuery.of( - context) - .size - .height * - 0.8), - shape: - const RoundedRectangleBorder( - borderRadius: - BorderRadius - .only( - topLeft: - Radius.circular( - 30), - topRight: - Radius.circular( - 30), - )), - context: context, - builder: (ctx) { - return const FilterPageSheet(); - }); - }, - child: SizedBox.expand( - child: Row( - mainAxisAlignment: - MainAxisAlignment - .center, - children: [ - Icon( - Icons - .filter_list_outlined, - color: themeProvider - .themeManager - .primaryTextColor, - size: 19, - ), - const CustomText( - ' Filters', - type: - FontStyle.Medium, - ) - ], - ), - ), - )), - ], - ), - ), - ], - ), - ) - : Container(), - ], - ), - ), - ), + child: issueProvider.statesState == StateEnum.restricted + ? EmptyPlaceholder.joinProject( + context, + ref, + projectProvider.currentProject['id'], + ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug) + : ProjectDetailRoot( + onTabChange: onTabChange, + selectedTab: selectedTab, + )), ); } } -Widget issues(BuildContext context, WidgetRef ref, {bool isViews = false}) { - final themeProvider = ref.watch(ProviderList.themeProvider); - final issueProvider = ref.watch(ProviderList.issuesProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); - // log(issueProvider.issueState.name); - if (issueProvider.issues.projectView == ProjectView.list && - !(issueProvider.issuePropertyState == StateEnum.loading || - issueProvider.issueState == StateEnum.loading || - issueProvider.statesState == StateEnum.loading || - issueProvider.projectViewState == StateEnum.loading || - issueProvider.orderByState == StateEnum.loading)) { - issueProvider.initializeBoard(views: isViews); - } - - return LoadingWidget( - loading: issueProvider.issuePropertyState == StateEnum.loading || - issueProvider.issueState == StateEnum.loading || - issueProvider.statesState == StateEnum.loading || - issueProvider.projectViewState == StateEnum.loading || - issueProvider.orderByState == StateEnum.loading, - widgetClass: issueProvider.statesState == StateEnum.restricted - ? EmptyPlaceholder.joinProject( - context, - ref, - projectProvider.currentProject['id'], - ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug) - : Container( - color: themeProvider.themeManager.secondaryBackgroundDefaultColor, - padding: issueProvider.issues.projectView == ProjectView.kanban - ? const EdgeInsets.only(top: 15, left: 0) - : null, - child: issueProvider.issueState == StateEnum.loading || - issueProvider.statesState == StateEnum.loading || - issueProvider.projectViewState == StateEnum.loading || - issueProvider.orderByState == StateEnum.loading - ? Container() - : issueProvider.groupByResponse.isEmpty && - issueProvider.issueState == StateEnum.success - ? Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - EmptyPlaceholder.emptyIssues(context, ref: ref), - ], - ) - : issueProvider.issues.projectView == ProjectView.list - ? Container( - color: themeProvider - .themeManager.secondaryBackgroundDefaultColor, - margin: const EdgeInsets.only(top: 5), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: issueProvider.issues.issues - .map((state) => state.items.isEmpty && - !issueProvider.showEmptyStates - ? Container() - : SizedBox( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Container( - padding: - const EdgeInsets.only( - left: 15), - margin: - const EdgeInsets.only( - bottom: 10), - child: Row( - children: [ - state.leading ?? - Container(), - Container( - padding: - const EdgeInsets - .only( - left: 10, - ), - width: MediaQuery.of( - context) - .size - .width * - 0.6, - child: CustomText( - state.title!, - overflow: - TextOverflow - .ellipsis, - maxLines: 1, - type: - FontStyle.Large, - color: themeProvider - .themeManager - .primaryTextColor, - fontWeight: - FontWeightt - .Semibold, - ), - ), - Container( - alignment: - Alignment.center, - margin: - const EdgeInsets - .only( - left: 15, - ), - decoration: BoxDecoration( - borderRadius: - BorderRadius - .circular( - 15), - color: themeProvider - .themeManager - .tertiaryBackgroundDefaultColor), - height: 25, - width: 30, - child: CustomText( - state.items.length - .toString(), - type: - FontStyle.Small, - ), - ), - const Spacer(), - projectProvider.role == - Role - .admin || - projectProvider - .role == - Role.member - ? IconButton( - onPressed: () { - if (issueProvider - .issues - .groupBY == - GroupBY - .state) { - issueProvider - .createIssuedata['state'] = - state - .id; - } else { - issueProvider - .createIssuedata['prioriry'] = - 'de3c90cd-25cd-42ec-ac6c-a66caf8029bc'; - // createIssuedata['s'] = element.id; - } - Navigator.of( - context) - .push(MaterialPageRoute( - builder: (ctx) => - const CreateIssue())); - }, - icon: Icon( - Icons.add, - color: themeProvider - .themeManager - .tertiaryTextColor, - )) - : Container( - height: 40, - ), - const SizedBox( - width: 10, - ), - ], - ), - ), - Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: state.items - .map((e) => e) - .toList()), - state.items.isEmpty - ? Container( - margin: - const EdgeInsets - .only( - bottom: 10), - width: MediaQuery.of( - context) - .size - .width, - color: themeProvider - .themeManager - .primaryBackgroundDefaultColor, - padding: - const EdgeInsets - .only( - top: 15, - bottom: 15, - left: 15), - child: - const CustomText( - 'No issues.', - type: - FontStyle.Small, - maxLines: 10, - textAlign: - TextAlign.start, - ), - ) - : Container( - margin: - const EdgeInsets - .only( - bottom: 10), - ) - ], - ), - )) - .toList()), - ), - ) - : issueProvider.issues.projectView == ProjectView.kanban - ? KanbanBoard( - issueProvider.initializeBoard(views: isViews), - boardID: 'issues-board', - isCardsDraggable: - issueProvider.checkIsCardsDaraggable(), - onItemReorder: ( - {newCardIndex, - newListIndex, - oldCardIndex, - oldListIndex}) { - // print('newCardIndex: $newCardIndex, newListIndex: $newListIndex, oldCardIndex: $oldCardIndex, oldListIndex: $oldListIndex'); - issueProvider - .reorderIssue( - context: context, - newCardIndex: newCardIndex!, - newListIndex: newListIndex!, - oldCardIndex: oldCardIndex!, - oldListIndex: oldListIndex!, - ) - .then((value) { - if (issueProvider.issues.orderBY != - OrderBY.manual) { - CustomToast.showToast(context, - message: - 'This board is ordered by ${issueProvider.issues.orderBY == OrderBY.lastUpdated ? 'last updated' : 'created at'} ', - toastType: ToastType.warning); - } - }).catchError((e) { - CustomToast.showToast(context, - message: 'Failed to update issue', - toastType: ToastType.failure); - }); - }, - groupEmptyStates: - !issueProvider.showEmptyStates, - backgroundColor: themeProvider.themeManager - .secondaryBackgroundDefaultColor, - cardPlaceHolderColor: themeProvider - .themeManager.primaryBackgroundDefaultColor, - cardPlaceHolderDecoration: BoxDecoration( - color: themeProvider.themeManager - .primaryBackgroundDefaultColor, - boxShadow: [ - BoxShadow( - blurRadius: 2, - color: themeProvider - .themeManager.borderSubtle01Color, - spreadRadius: 0, - ), - ]), - listScrollConfig: ScrollConfig( - offset: 65, - duration: const Duration(milliseconds: 100), - curve: Curves.linear), - boardScrollConfig: ScrollConfig( - offset: 45, - duration: const Duration(milliseconds: 100), - curve: Curves.linear), - listTransitionDuration: - const Duration(milliseconds: 200), - cardTransitionDuration: - const Duration(milliseconds: 400), - ) - : issueProvider.issues.projectView == - ProjectView.calendar - ? const CalendarView() - : const SpreadSheetView( - issueCategory: IssueCategory.issues, - ), - ), - ); -} - Widget cycles() { return const CycleWidget(); } @@ -1089,22 +100,9 @@ Widget view(WidgetRef ref) { child: const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // SizedBox( - // child: Text( - // 'Current Cycles', - // style: TextStyle(fontSize: 20, fontWeight: FontWeightt.Medium), - // ), - // ), Views() ], ), ); } -// bool checkVisbility(int index) { -// final featuresProvider = ref.watch(ProviderList.featuresProvider); -// if(featuresProvider.features[index]['title'] == featuresProvider.features[index]){ -// return true; -// } -// return false; -// } diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart new file mode 100644 index 00000000..9c7f506d --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/create_cycle.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ModulesTab/create_module.dart'; +import 'package:plane/screens/create_view_screen.dart'; +import 'package:plane/utils/enums.dart'; + +// ignore: non_constant_identifier_names +Widget FLActionButton( + BuildContext context, { + required WidgetRef ref, + required int selected, +}) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + final cycleProvider = ref.watch(ProviderList.cyclesProvider); + final moduleProvider = ref.watch(ProviderList.modulesProvider); + final viewsProvider = ref.watch(ProviderList.viewsProvider); + + return selected != 0 && + (projectProvider.role == Role.admin || + projectProvider.role == Role.member) && + ((selected == 1 && cycleProvider.showAddFloatingButton()) || + (selected == 2 && + moduleProvider.moduleState != StateEnum.loading && + (moduleProvider.modules.isNotEmpty || + moduleProvider.favModules.isNotEmpty)) || + (selected == 3 && + viewsProvider.viewsState != StateEnum.loading && + viewsProvider.views.isNotEmpty)) + ? FloatingActionButton( + backgroundColor: themeProvider.themeManager.primaryColour, + child: Icon( + Icons.add, + color: themeProvider.themeManager.textonColor, + ), + onPressed: () { + if (selected == 1 && projectProvider.features[1]['show']) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => const CreateCycle(), + ), + ); + } + + if (selected == 1 && + !projectProvider.features[1]['show'] && + projectProvider.features[2]['show']) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => const CreateModule(), + ), + ); + } + + if (selected == 1 && + !projectProvider.features[1]['show'] && + !projectProvider.features[2]['show']) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => const CreateView(), + ), + ); + } + + if (selected == 2 && + projectProvider.features[2]['show'] && + projectProvider.features[1]['show']) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => const CreateModule(), + ), + ); + } + + if ((selected == 2 && + projectProvider.features[2]['show'] && + !projectProvider.features[1]['show']) || + (selected == 2 && + !projectProvider.features[2]['show'] && + projectProvider.features[1]['show'])) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => const CreateView(), + ), + ); + } + if (selected == 3) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => const CreateView(), + ), + ); + } + // if (selected == 4) { + // Navigator.of(context).push( + // MaterialPageRoute( + // builder: (ctx) => const CreatePage(), + // ), + // ); + // } + }, + ) + : Container(); +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart new file mode 100644 index 00000000..d7abdec0 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart'; +import 'package:plane/screens/settings_screen.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/custom_app_bar.dart'; + +// ignore: non_constant_identifier_names +PreferredSizeWidget ProjectDetailAppbar( + BuildContext context, { + required WidgetRef ref, + required VoidCallback settingsOntap, +}) { + final themeProvider = ref.read(ProviderList.themeProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + final issueProvider = ref.read(ProviderList.issuesProvider); + + return CustomAppBar( + elevation: false, + onPressed: () { + Navigator.pop(context); + }, + text: projectProvider.currentProject['name'], + actions: [ + (projectProvider.currentProject['archive_in'] > 0 && + (projectProvider.role == Role.admin || + projectProvider.role == Role.member) && + (issueProvider.statesState == StateEnum.success)) + ? IconButton( + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => const ArchivedIssues(), + ), + ); + }, + icon: Icon( + Icons.archive_outlined, + color: themeProvider.themeManager.placeholderTextColor, + )) + : Container(), + (issueProvider.statesState == StateEnum.success) + ? IconButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const SettingScreen(), + ), + ).then((value) { + settingsOntap(); + }); + }, + icon: issueProvider.statesState == StateEnum.restricted + ? Container() + : Icon( + Icons.settings_outlined, + color: themeProvider.themeManager.placeholderTextColor, + ), + ) + : Container(), + ], + ); +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart new file mode 100644 index 00000000..73d20140 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart @@ -0,0 +1,293 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom_sheets/page_filter_sheet.dart'; +import 'package:plane/bottom_sheets/type_sheet.dart'; +import 'package:plane/bottom_sheets/views_sheet.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/create_page_screen.dart'; +import 'package:plane/utils/bottom_sheet.helper.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/custom_text.dart'; + +class ProjectDetailBottomActions extends ConsumerStatefulWidget { + const ProjectDetailBottomActions({required this.selectedTab, super.key}); + final int selectedTab; + @override + ConsumerState createState() => + _PDBottomActionsState(); +} + +class _PDBottomActionsState extends ConsumerState { + @override + Widget build(BuildContext context) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + final issueProvider = ref.watch(ProviderList.issuesProvider); + final pageProvider = ref.watch(ProviderList.pageProvider); + + return Row( + children: [ + issueProvider.statesState == StateEnum.loading || + issueProvider.issueState == StateEnum.loading + ? Container() + : widget.selectedTab == 0 && + issueProvider.statesState == StateEnum.restricted + ? Container() + : widget.selectedTab == 0 && + issueProvider.statesState == StateEnum.success + ? Container( + decoration: BoxDecoration( + color: themeProvider + .themeManager.primaryBackgroundDefaultColor, + boxShadow: themeProvider + .themeManager.shadowBottomControlButtons, + ), + height: 50, + width: MediaQuery.of(context).size.width, + child: Row( + children: [ + projectProvider.role == Role.admin || + projectProvider.role == Role.member + ? Expanded( + child: InkWell( + onTap: () { + issueProvider.createIssuedata['state'] = + issueProvider.states.keys.first; + + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + const CreateIssue(), + ), + ); + }, + child: SizedBox.expand( + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.add, + color: themeProvider.themeManager + .primaryTextColor, + size: 20, + ), + const CustomText( + ' Issue', + type: FontStyle.Medium, + ) + ], + ), + ), + ), + ) + : Container(), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + Expanded( + child: InkWell( + onTap: () { + BottomSheetHelper.showBottomSheet( + context, + const TypeSheet( + issueCategory: IssueCategory.issues, + ), + constraints: BoxConstraints( + maxHeight: + MediaQuery.of(context).size.height * + 0.5), + ); + }, + child: SizedBox.expand( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.list_outlined, + color: themeProvider + .themeManager.primaryTextColor, + size: 19, + ), + const CustomText( + ' Layout', + type: FontStyle.Medium, + ) + ], + ), + ), + )), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + issueProvider.issues.projectView == + IssueLayout.calendar + ? Container() + : Expanded( + child: InkWell( + onTap: () { + BottomSheetHelper.showBottomSheet( + context, + ViewsSheet( + projectView: issueProvider + .issues.projectView, + issueCategory: IssueCategory.issues, + )); + }, + child: SizedBox.expand( + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.wysiwyg_outlined, + color: themeProvider + .themeManager.primaryTextColor, + size: 19, + ), + const CustomText( + ' Display', + type: FontStyle.Medium, + ) + ], + ), + ), + )), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + Expanded( + child: InkWell( + onTap: () { + BottomSheetHelper.showBottomSheet( + context, + FilterSheet( + issueCategory: IssueCategory.issues, + )); + }, + child: SizedBox.expand( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.filter_list_outlined, + color: themeProvider + .themeManager.primaryTextColor, + size: 19, + ), + const CustomText( + ' Filters', + type: FontStyle.Medium, + ) + ], + ), + ), + )), + ], + ), + ) + : Container(), + widget.selectedTab == 4 + ? widget.selectedTab == 4 && + pageProvider.pages[pageProvider.selectedFilter]!.isEmpty + ? Container() + : Container( + height: 51, + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + color: themeProvider + .themeManager.primaryBackgroundDefaultColor, + boxShadow: + themeProvider.themeManager.shadowBottomControlButtons, + ), + child: Column( + children: [ + SizedBox( + height: 50, + child: Row( + children: [ + projectProvider.role == Role.admin + ? Expanded( + child: InkWell( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + const CreatePage(), + ), + ); + }, + child: SizedBox.expand( + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.add, + color: themeProvider + .themeManager + .primaryTextColor, + size: 20, + ), + const CustomText( + ' Page', + type: FontStyle.Medium, + ) + ], + ), + ), + ), + ) + : Container(), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + Expanded( + child: InkWell( + onTap: () { + BottomSheetHelper.showBottomSheet( + context, const FilterPageSheet()); + }, + child: SizedBox.expand( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.filter_list_outlined, + color: themeProvider + .themeManager.primaryTextColor, + size: 19, + ), + const CustomText( + ' Filters', + type: FontStyle.Medium, + ) + ], + ), + ), + )), + ], + ), + ), + ], + ), + ) + : Container(), + ], + ); + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart new file mode 100644 index 00000000..d43fa631 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart @@ -0,0 +1,94 @@ +// ignore_for_file: non_constant_identifier_names + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/error_state.dart'; + +class ProjectDetailRoot extends ConsumerStatefulWidget { + const ProjectDetailRoot( + {required this.onTabChange, required this.selectedTab, super.key}); + final int selectedTab; + final void Function(int index) onTabChange; + + @override + ConsumerState createState() => _ProjectDetailRootState(); +} + +class _ProjectDetailRootState extends ConsumerState { + List TABS = []; + final controller = PageController(); + + void initializeTabs() { + final projectProvider = ref.read(ProviderList.projectProvider); + TABS = [ + ProjectDetailTab(title: 'Issues', width: 60, show: true), + ProjectDetailTab( + title: 'Cycles', + width: 60, + show: projectProvider.features[1]['show']), + ProjectDetailTab( + title: 'Modules', + width: 75, + show: projectProvider.features[2]['show']), + ProjectDetailTab( + title: 'Views', width: 60, show: projectProvider.features[3]['show']), + ]; + } + + @override + void initState() { + initializeTabs(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final issueProvider = ref.watch(ProviderList.issuesProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + + return projectProvider.projectDetailState == StateEnum.error + ? errorState( + context: context, + ontap: () { + ref + .read(ProviderList.projectProvider) + .initializeProject(ref: ref); + }) + : Column( + children: [ + issueProvider.statesState != StateEnum.loading + ? ProjectDetailTabs( + selectedTab: widget.selectedTab, + onTabChange: widget.onTabChange, + TABS: TABS, + ) + : Container(), + Container( + height: 2, + width: MediaQuery.of(context).size.width, + color: themeProvider.themeManager.borderSubtle01Color, + ), + Expanded( + child: PageView.builder( + controller: controller, + onPageChanged: (page) { + widget.onTabChange(page); + }, + itemBuilder: (ctx, index) { + return index == 0 ? const IssuesTab() : Container(); + }, + itemCount: TABS.length, + ), + ), + ProjectDetailBottomActions(selectedTab: widget.selectedTab) + ], + ); + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart new file mode 100644 index 00000000..baa0209f --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart @@ -0,0 +1,69 @@ +// ignore_for_file: non_constant_identifier_names + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/custom_text.dart'; + +class ProjectDetailTabs extends ConsumerWidget { + const ProjectDetailTabs( + {required this.TABS, + required this.selectedTab, + required this.onTabChange, + super.key}); + final List TABS; + final int selectedTab; + final void Function(int) onTabChange; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final themeProvider = ref.watch(ProviderList.themeProvider); + return Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: TABS.map((tab) { + final tabIndex = TABS.indexOf(tab); + return tab.show + ? Expanded( + child: InkWell( + onTap: () { + onTabChange(tabIndex); + }, + child: Column( + children: [ + Container( + margin: const EdgeInsets.symmetric(vertical: 8), + child: CustomText( + tab.title, + color: tabIndex == selectedTab + ? themeProvider.themeManager.primaryColour + : themeProvider.themeManager.placeholderTextColor, + overrride: true, + type: FontStyle.Medium, + fontWeight: tabIndex == selectedTab + ? FontWeightt.Medium + : null, + ), + ), + selectedTab == TABS.indexOf(tab) && + TABS.elementAt(tabIndex).show + ? Container( + height: 6, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: themeProvider.themeManager.primaryColour, + ), + ) + : Container( + height: 6, + ) + ], + ), + ), + ) + : Container(); + }).toList(), + ); + } +} diff --git a/lib/utils/enums.dart b/lib/utils/enums.dart index 8b11fbb3..3d0dd38d 100644 --- a/lib/utils/enums.dart +++ b/lib/utils/enums.dart @@ -18,7 +18,7 @@ enum PageFilters { all, recent, favourites, createdByMe, createdByOthers } enum HttpMethod { connect, delete, get, head, options, patch, post, put, trace } -enum ProjectView { kanban, list, calendar, spreadsheet } +enum IssueLayout { kanban, list, calendar, spreadsheet } enum GroupBY { state, diff --git a/lib/widgets/issue_card_widget.dart b/lib/widgets/issue_card_widget.dart index d9f0f7ad..6159b9e3 100644 --- a/lib/widgets/issue_card_widget.dart +++ b/lib/widgets/issue_card_widget.dart @@ -90,12 +90,12 @@ class _IssueCardWidgetState extends ConsumerState { .watch(ProviderList.myIssuesProvider) .issues .projectView == - ProjectView.list + IssueLayout.list : ref .watch(ProviderList.issuesProvider) .issues .projectView == - ProjectView.list) + IssueLayout.list) ? const EdgeInsets.only(bottom: 1) : const EdgeInsets.only(bottom: 15, right: 5, left: 5, top: 5), decoration: BoxDecoration( @@ -105,12 +105,12 @@ class _IssueCardWidgetState extends ConsumerState { .watch(ProviderList.myIssuesProvider) .issues .projectView == - ProjectView.kanban + IssueLayout.kanban : ref .watch(ProviderList.issuesProvider) .issues .projectView == - ProjectView.kanban) + IssueLayout.kanban) ? [ BoxShadow( blurRadius: 2, @@ -126,7 +126,7 @@ class _IssueCardWidgetState extends ConsumerState { .watch(ProviderList.issuesProvider) .issues .projectView == - ProjectView.list + IssueLayout.list ? width : widget.issueCategory == IssueCategory.moduleIssues ? width @@ -152,12 +152,12 @@ class _IssueCardWidgetState extends ConsumerState { .watch(ProviderList.myIssuesProvider) .issues .projectView == - ProjectView.list + IssueLayout.list : ref .watch(ProviderList.issuesProvider) .issues .projectView == - ProjectView.list) + IssueLayout.list) ? listCard() : kanbanCard()), ), @@ -166,9 +166,9 @@ class _IssueCardWidgetState extends ConsumerState { .watch(ProviderList.myIssuesProvider) .issues .projectView == - ProjectView.list + IssueLayout.list : ref.watch(ProviderList.issuesProvider).issues.projectView == - ProjectView.list) + IssueLayout.list) ? Divider( height: 1, thickness: 1, From 162cc4232ce669b88822208dda1d01931fceec3a Mon Sep 17 00:00:00 2001 From: ramesh kumar Date: Wed, 17 Jan 2024 20:17:15 +0530 Subject: [PATCH 4/7] refactor: states feature refactor --- lib/bottom_sheets/delete_state_sheet.dart | 30 +-- lib/bottom_sheets/filters/filter_sheet.dart | 1 + .../filters/widgets/state_filter.dart | 4 +- lib/bottom_sheets/select_states.dart | 11 +- lib/config/apis.dart | 5 +- lib/models/states_model.dart | 83 ++++++ lib/provider/cycles_provider.dart | 8 +- lib/provider/issues_provider.dart | 118 ++------ lib/provider/modules_provider.dart | 8 +- lib/provider/projects_provider.dart | 72 +---- lib/provider/provider_list.dart | 6 + lib/provider/states_provider.dart | 185 +++++++++++++ lib/provider/workspace_provider.dart | 5 +- lib/repository/profile_provider_service.dart | 4 +- lib/repository/states_service.dart | 130 +++++++++ .../IssuesTab/CreateIssue/create_issue.dart | 50 ++-- .../ProjectDetail/Settings/states_pages.dart | 253 +++++++++++------- lib/screens/create_view_screen.dart | 5 +- 18 files changed, 645 insertions(+), 333 deletions(-) create mode 100644 lib/models/states_model.dart create mode 100644 lib/provider/states_provider.dart create mode 100644 lib/repository/states_service.dart diff --git a/lib/bottom_sheets/delete_state_sheet.dart b/lib/bottom_sheets/delete_state_sheet.dart index 06e29125..0b8ca099 100644 --- a/lib/bottom_sheets/delete_state_sheet.dart +++ b/lib/bottom_sheets/delete_state_sheet.dart @@ -21,11 +21,11 @@ class DeleteStateSheet extends ConsumerStatefulWidget { class _DeleteStateSheetState extends ConsumerState { @override Widget build(BuildContext context) { - final projectProvider = ref.watch(ProviderList.projectProvider); final themeProvider = ref.watch(ProviderList.themeProvider); - final issuesProvider = ref.watch(ProviderList.issuesProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); + final statesProviderRead = ref.watch(ProviderList.statesProvider.notifier); return LoadingWidget( - loading: projectProvider.stateCrudState == StateEnum.loading, + loading: statesProvider.deleteState == StateEnum.loading, allowBorderRadius: true, widgetClass: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 30), @@ -70,31 +70,11 @@ class _DeleteStateSheetState extends ConsumerState { Button( color: const Color.fromRGBO(254, 242, 242, 1), textColor: themeProvider.themeManager.textErrorColor, - filledButton: false, borderColor: themeProvider.themeManager.textErrorColor, text: 'Delete', ontap: () async { - await projectProvider.stateCrud( - slug: ref - .watch(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projId: ref - .watch(ProviderList.projectProvider) - .currentProject['id'], - method: CRUD.delete, - stateId: widget.stateId, - context: context, - data: {}, - ref: ref); - issuesProvider.getStates( - slug: ref - .watch(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: ref - .watch(ProviderList.projectProvider) - .currentProject['id'], + await statesProviderRead.deleteState( + stateId: widget.stateId, ); Navigator.of(context).pop(); }, diff --git a/lib/bottom_sheets/filters/filter_sheet.dart b/lib/bottom_sheets/filters/filter_sheet.dart index 41173514..7f4fba06 100644 --- a/lib/bottom_sheets/filters/filter_sheet.dart +++ b/lib/bottom_sheets/filters/filter_sheet.dart @@ -10,6 +10,7 @@ import 'package:plane/provider/cycles_provider.dart'; import 'package:plane/provider/modules_provider.dart'; import 'package:plane/provider/my_issues_provider.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/provider/states_provider.dart'; import 'package:plane/provider/theme_provider.dart'; import 'package:plane/screens/create_view_screen.dart'; import 'package:plane/utils/constants.dart'; diff --git a/lib/bottom_sheets/filters/widgets/state_filter.dart b/lib/bottom_sheets/filters/widgets/state_filter.dart index 49af85de..8f6fdcb0 100644 --- a/lib/bottom_sheets/filters/widgets/state_filter.dart +++ b/lib/bottom_sheets/filters/widgets/state_filter.dart @@ -12,13 +12,13 @@ class __StateFilterState extends ConsumerState<_StateFilter> { @override Widget build(BuildContext context) { final ThemeProvider themeProvider = ref.read(ProviderList.themeProvider); - final IssuesProvider issuesProvider = ref.read(ProviderList.issuesProvider); + final statesProvider = ref.read(ProviderList.statesProvider); return CustomExpansionTile( title: 'State', child: Wrap( children: (widget.state.issueCategory == IssueCategory.myIssues ? widget.state.states - : issuesProvider.states.values) + : statesProvider.projectStates.values) .map((e) { final String key = widget.state.issueCategory == IssueCategory.myIssues ? 'id' diff --git a/lib/bottom_sheets/select_states.dart b/lib/bottom_sheets/select_states.dart index 401d08dc..1837492f 100644 --- a/lib/bottom_sheets/select_states.dart +++ b/lib/bottom_sheets/select_states.dart @@ -23,13 +23,14 @@ class _SelectStatesState extends ConsumerState { @override void initState() { final prov = ref.read(ProviderList.issuesProvider); + final statesProvider = ref.watch(ProviderList.statesProvider.notifier); if (prov.states.isEmpty) { - prov.getStates( + statesProvider.getStates( slug: ref .read(ProviderList.workspaceProvider) .selectedWorkspace .workspaceSlug, - projID: ref + projectId: ref .read(ProviderList.issuesProvider) .createIssueProjectData['id']); } @@ -268,16 +269,18 @@ class _SelectStatesState extends ConsumerState { IconButton( onPressed: () { final prov = ref.read(ProviderList.issuesProvider); + final statesProvider = + ref.watch(ProviderList.statesProvider.notifier); // if (selectedState.isNotEmpty) { prov.createIssuedata['state'] = selectedState; // print('state'); // print(prov.createIssuedata['state'].toString()); - prov.getStates( + statesProvider.getStates( slug: ref .read(ProviderList.workspaceProvider) .selectedWorkspace .workspaceSlug, - projID: ref + projectId: ref .read(ProviderList.projectProvider) .currentProject['id']); prov.setsState(); diff --git a/lib/config/apis.dart b/lib/config/apis.dart index 66c608f9..6c60a236 100644 --- a/lib/config/apis.dart +++ b/lib/config/apis.dart @@ -8,10 +8,9 @@ class APIs { static String generateMagicLink = '/api/magic-generate/'; static String googleAuth = '$baseApi/api/social-auth/'; static String magicValidate = '/api/magic-sign-in/'; - static String profile = '/api/users/me/'; + static String profile = '$baseApi/api/users/me/'; static String listWorkspaceInvitaion = - '/api/users/me/invitations/workspaces/'; - static String joinWorkspace = '$baseApi/api/users/me/invitations/workspaces/'; + '$baseApi/api/users/me/workspaces/invitations/'; static String createWorkspace = '$baseApi/api/workspaces/'; static String inviteToWorkspace = '$baseApi/api/workspaces/\$SLUG/invite/'; static String inviteToProject = diff --git a/lib/models/states_model.dart b/lib/models/states_model.dart new file mode 100644 index 00000000..e9da8458 --- /dev/null +++ b/lib/models/states_model.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; + +class StatesModel { + StatesModel( + {required this.id, + this.createdAt, + this.updatedAt, + this.name, + this.description, + this.color, + this.slug, + this.sequence, + this.group, + this.isDefault, + this.externalSource, + this.externalId, + this.createdBy, + this.updatedBy, + this.project, + this.workspace, + this.stateIcon}); + + factory StatesModel.fromJson(Map json) { + return StatesModel( + id: json['id'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + name: json['name'], + description: json['description'], + color: json['color'], + slug: json['slug'], + sequence: json['sequence']?.toDouble(), + group: json['group'], + isDefault: json['default'], + externalSource: json['external_source'], + externalId: json['external_id'], + createdBy: json['created_by'], + updatedBy: json['updated_by'], + project: json['project'], + workspace: json['workspace'], + stateIcon: null); + } + + final String id; + final String? createdAt; + final String? updatedAt; + final String? name; + final String? description; + final String? color; + final String? slug; + final double? sequence; + final String? group; + final bool? isDefault; + final String? externalSource; + final String? externalId; + final String? createdBy; + final String? updatedBy; + final String? project; + final String? workspace; + Widget? stateIcon; + + StatesModel empty() { + return StatesModel( + id: '', + createdAt: '', + updatedAt: '', + name: '', + description: '', + color: '', + slug: '', + sequence: 0, + group: '', + isDefault: false, + externalSource: '', + externalId: '', + createdBy: '', + updatedBy: '', + project: '', + workspace: '', + stateIcon: null + ); + } +} diff --git a/lib/provider/cycles_provider.dart b/lib/provider/cycles_provider.dart index 02ebb782..c22eba0d 100644 --- a/lib/provider/cycles_provider.dart +++ b/lib/provider/cycles_provider.dart @@ -437,7 +437,7 @@ class CyclesProvider with ChangeNotifier { var title = issues.groupBY == GroupBY.priority ? groupID : issues.groupBY == GroupBY.state - ? issuesProvider.states[groupID]['name'] + ? issuesProvider.states[groupID]!.name : groupID; issues.issues.add(BoardListsData( id: groupID, @@ -897,15 +897,15 @@ class CyclesProvider with ChangeNotifier { notifyListeners(); final issuesProvider = ref.read(ProviderList.issuesProvider); final projectProvider = ref.read(ProviderList.projectProvider); + final statesProvider = ref.read(ProviderList.statesProvider.notifier); if (issues.groupBY == GroupBY.labels) { issuesProvider.getLabels(slug: slug, projID: projectId); } else if (issues.groupBY == GroupBY.createdBY) { projectProvider.getProjectMembers(slug: slug, projId: projectId); } else if (issues.groupBY == GroupBY.state) { - issuesProvider.getStates( + statesProvider.getStates( slug: slug, - projID: projectId, - showLoading: false, + projectId: projectId, ); } diff --git a/lib/provider/issues_provider.dart b/lib/provider/issues_provider.dart index 7168ac61..213e06ac 100644 --- a/lib/provider/issues_provider.dart +++ b/lib/provider/issues_provider.dart @@ -8,6 +8,7 @@ import 'package:intl/intl.dart'; import 'package:plane/config/const.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; +import 'package:plane/models/states_model.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; import 'package:plane/utils/constants.dart'; @@ -62,7 +63,7 @@ class IssuesProvider extends ChangeNotifier { List issuesResponse = []; List issuesList = []; List labels = []; - Map states = {}; + Map states = {}; Map statesData = {}; // List members = []; Map projectView = {}; @@ -265,7 +266,7 @@ class IssuesProvider extends ChangeNotifier { String title = issues.groupBY == GroupBY.priority ? groupID : issues.groupBY == GroupBY.state - ? states[groupID]['name'] + ? states[groupID]!.name : groupID; issues.issues.add(BoardListsData( id: groupID, @@ -658,82 +659,6 @@ class IssuesProvider extends ChangeNotifier { } } - Future getStates({ - required String slug, - required String projID, - bool showLoading = true, - }) async { - if (showLoading) { - statesState = StateEnum.loading; - notifyListeners(); - } - try { - final response = await DioConfig().dioServe( - hasAuth: true, - url: APIs.states - .replaceAll("\$SLUG", slug) - .replaceAll('\$PROJECTID', projID), - hasBody: false, - httpMethod: HttpMethod.get, - ); - // log(response.data.toString()); - statesData = {for (final value in response.data) value['id']: value}; - states = {}; - for (int i = 0; i < statesData.length; i++) { - final String stateId = statesData.keys.elementAt(i); - states[stateId] = statesData[stateId]; - stateIcons[stateId] = SvgPicture.asset( - stateId == 'backlog' - ? 'assets/svg_images/circle.svg' - : stateId == 'cancelled' - ? 'assets/svg_images/cancelled.svg' - : stateId == 'completed' - ? 'assets/svg_images/done.svg' - : stateId == 'started' - ? 'assets/svg_images/in_progress.svg' - : 'assets/svg_images/unstarted.svg', - height: 22, - width: 22, - colorFilter: int.tryParse( - "FF${statesData[stateId]['color'].toString().replaceAll('#', '')}", - radix: 16) != - null - ? ColorFilter.mode( - Color(int.parse( - "FF${statesData[stateId]['color'].toString().replaceAll('#', '')}", - radix: 16)), - BlendMode.srcIn) - : null); - - if (statesData[stateId]['default'] == true) { - defaultStatedetails[stateId] = { - 'name': statesData[stateId]['name'], - 'icon': stateIcons[statesData[stateId]['id']] - }; - } - } - stateOrdering = []; - for (final element in defaultStateGroups) { - if (statesData[element] != null) { - for (final element in (statesData[element] as List)) { - stateOrdering.add(element['id']); - } - } - } - statesState = StateEnum.success; - notifyListeners(); - } on DioException catch (e) { - log(e.response!.statusCode.toString()); - if (e.response!.statusCode == 403) { - statesState = StateEnum.restricted; - notifyListeners(); - } else { - statesState = StateEnum.error; - notifyListeners(); - } - } - } - Future createIssue( {required String slug, required String projID, @@ -910,7 +835,7 @@ class IssuesProvider extends ChangeNotifier { hasBody: true, httpMethod: HttpMethod.post, data: data); - getStates(slug: slug, projID: projID); + ref!.read(ProviderList.statesProvider.notifier).getStates(slug: slug, projectId: projID); statesState = StateEnum.success; notifyListeners(); } on DioException catch (e) { @@ -983,10 +908,12 @@ class IssuesProvider extends ChangeNotifier { issueProperty['display_properties']['assignee']; issues.displayProperties.dueDate = issueProperty['display_properties']['due_date']; - issues.displayProperties.id = issueProperty['display_properties']['key']; + issues.displayProperties.id = + issueProperty['display_properties']['key']; issues.displayProperties.label = issueProperty['display_properties']['labels']; - issues.displayProperties.state = issueProperty['display_properties']['state']; + issues.displayProperties.state = + issueProperty['display_properties']['state']; issues.displayProperties.subIsseCount = issueProperty['display_properties']['sub_issue_count']; issues.displayProperties.linkCount = @@ -1017,12 +944,13 @@ class IssuesProvider extends ChangeNotifier { cyclesProvider.issueProperty['display_properties']['labels']; cyclesProvider.issues.displayProperties.state = cyclesProvider.issueProperty['display_properties']['state']; - cyclesProvider.issues.displayProperties.subIsseCount = - cyclesProvider.issueProperty['display_properties']['sub_issue_count']; + cyclesProvider.issues.displayProperties.subIsseCount = cyclesProvider + .issueProperty['display_properties']['sub_issue_count']; cyclesProvider.issues.displayProperties.linkCount = cyclesProvider.issueProperty['display_properties']['link']; cyclesProvider.issues.displayProperties.attachmentCount = - cyclesProvider.issueProperty['display_properties']['attachment_count']; + cyclesProvider.issueProperty['display_properties'] + ['attachment_count']; cyclesProvider.issues.displayProperties.priority = cyclesProvider.issueProperty['display_properties']['priority']; cyclesProvider.issues.displayProperties.estimate = @@ -1044,20 +972,22 @@ class IssuesProvider extends ChangeNotifier { modulesProvider.issues.displayProperties.state = modulesProvider.issueProperty['display_properties']['state']; modulesProvider.issues.displayProperties.subIsseCount = - modulesProvider.issueProperty['display_properties']['sub_issue_count']; + modulesProvider.issueProperty['display_properties'] + ['sub_issue_count']; modulesProvider.issues.displayProperties.linkCount = modulesProvider.issueProperty['display_properties']['link']; modulesProvider.issues.displayProperties.attachmentCount = - modulesProvider.issueProperty['display_properties']['attachment_count']; + modulesProvider.issueProperty['display_properties'] + ['attachment_count']; modulesProvider.issues.displayProperties.priority = modulesProvider.issueProperty['display_properties']['priority']; modulesProvider.issues.displayProperties.estimate = modulesProvider.issueProperty['display_properties']['estimate']; modulesProvider.issues.displayProperties.startDate = modulesProvider.issueProperty['display_properties']['start_date']; - modulesProvider.issues.displayProperties.createdOn = - modulesProvider.issueProperty['display_properties']?['created_on'] ?? - false; + modulesProvider.issues.displayProperties.createdOn = modulesProvider + .issueProperty['display_properties']?['created_on'] ?? + false; modulesProvider.issues.displayProperties.updatedOn = modulesProvider.issueProperty['display_properties']['updated_on']; ref!.read(ProviderList.modulesProvider).issues.displayProperties = @@ -1068,10 +998,12 @@ class IssuesProvider extends ChangeNotifier { issueProperty['display_properties']['assignee']; issues.displayProperties.dueDate = issueProperty['display_properties']['due_date']; - issues.displayProperties.id = issueProperty['display_properties']['key']; + issues.displayProperties.id = + issueProperty['display_properties']['key']; issues.displayProperties.label = issueProperty['display_properties']['labels']; - issues.displayProperties.state = issueProperty['display_properties']['state']; + issues.displayProperties.state = + issueProperty['display_properties']['state']; issues.displayProperties.subIsseCount = issueProperty['display_properties']['sub_issue_count']; issues.displayProperties.linkCount = @@ -1328,10 +1260,10 @@ class IssuesProvider extends ChangeNotifier { projId: projID, ); } else if (issues.groupBY == GroupBY.state) { + ref!.read(ProviderList.statesProvider.notifier). getStates( slug: slug, - projID: projID, - showLoading: false, + projectId: projID, ); } diff --git a/lib/provider/modules_provider.dart b/lib/provider/modules_provider.dart index 63e3f1b5..bee97c72 100644 --- a/lib/provider/modules_provider.dart +++ b/lib/provider/modules_provider.dart @@ -424,15 +424,15 @@ class ModuleProvider with ChangeNotifier { notifyListeners(); final issuesProvider = ref.watch(ProviderList.issuesProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final statesProvider = ref.watch(ProviderList.statesProvider.notifier); if (issues.groupBY == GroupBY.labels) { issuesProvider.getLabels(slug: slug, projID: projectId); } else if (issues.groupBY == GroupBY.createdBY) { projectProvider.getProjectMembers(slug: slug, projId: projectId); } else if (issues.groupBY == GroupBY.state) { - issuesProvider.getStates( + statesProvider.getStates( slug: slug, - projID: projectId, - showLoading: false, + projectId: projectId, ); } @@ -546,7 +546,7 @@ class ModuleProvider with ChangeNotifier { var title = issues.groupBY == GroupBY.priority ? groupID : issues.groupBY == GroupBY.state - ? issuesProvider.states[groupID]['name'] + ? issuesProvider.states[groupID]!.name : groupID; issues.issues.add(BoardListsData( id: groupID, diff --git a/lib/provider/projects_provider.dart b/lib/provider/projects_provider.dart index 4769547b..34e37029 100644 --- a/lib/provider/projects_provider.dart +++ b/lib/provider/projects_provider.dart @@ -92,6 +92,7 @@ class ProjectsProvider extends ChangeNotifier { final viewsProvider = ref.read(ProviderList.viewsProvider.notifier); final intergrationProvider = ref.read(ProviderList.integrationProvider); final workspaceProvider = ref.read(ProviderList.workspaceProvider); + final statesProvider = ref.watch(ProviderList.statesProvider.notifier); // final pageProv = ref.read(ProviderList.pageProvider); if (currentProject['estimate'] != null && currentProject['estimate'] != '') { @@ -102,7 +103,7 @@ class ProjectsProvider extends ChangeNotifier { .selectedWorkspace .workspaceSlug; - prov.getStates(slug: workspaceSlug, projID: currentProject['id']); + statesProvider.getStates(slug: workspaceSlug, projectId: currentProject['id']); getProjectMembers( slug: workspaceSlug, projId: currentProject['id'], @@ -673,73 +674,4 @@ class ProjectsProvider extends ChangeNotifier { } } - Future stateCrud( - {required String slug, - required String projId, - required String stateId, - required CRUD method, - required BuildContext context, - required WidgetRef ref, - required Map data}) async { - final workspaceProvider = ref.watch(ProviderList.workspaceProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); - try { - final url = method == CRUD.update || method == CRUD.delete - ? '${APIs.states.replaceFirst('\$SLUG', slug).replaceFirst('\$PROJECTID', projId)}$stateId/' - : APIs.states - .replaceFirst('\$SLUG', slug) - .replaceFirst('\$PROJECTID', projId); - stateCrudState = StateEnum.loading; - notifyListeners(); - final response = await DioConfig().dioServe( - hasAuth: true, - url: url, - hasBody: true, - httpMethod: method == CRUD.create - ? HttpMethod.post - : method == CRUD.update - ? HttpMethod.put - : method == CRUD.delete - ? HttpMethod.delete - : HttpMethod.patch, - data: data); - stateCrudState = StateEnum.success; - method != CRUD.read - ? postHogService( - eventName: method == CRUD.create - ? 'STATE_CREATE' - : method == CRUD.update - ? 'STATE_UPDATE' - : method == CRUD.delete - ? 'STATE_DELETE' - : '', - properties: method == CRUD.delete - ? {} - : { - 'WORKSPACE_ID': - workspaceProvider.selectedWorkspace.workspaceId, - 'WORKSPACE_SLUG': - workspaceProvider.selectedWorkspace.workspaceSlug, - 'WORKSPACE_NAME': - workspaceProvider.selectedWorkspace.workspaceName, - 'PROJECT_ID': projectProvider.projectDetailModel!.id, - 'PROJECT_NAME': projectProvider.projectDetailModel!.name, - 'STATE_ID': - method == CRUD.create ? response.data['id'] : stateId - }, - ref: ref) - : null; - notifyListeners(); - } catch (e) { - if (e is DioException) { - log(e.message.toString()); - } - CustomToast.showToast(context, - message: 'Something went wrong, Please try again.', - toastType: ToastType.failure); - log(e.toString()); - stateCrudState = StateEnum.error; - notifyListeners(); - } - } } diff --git a/lib/provider/provider_list.dart b/lib/provider/provider_list.dart index d77f8582..f60e2a52 100644 --- a/lib/provider/provider_list.dart +++ b/lib/provider/provider_list.dart @@ -16,8 +16,10 @@ import 'package:plane/provider/notification_provider.dart'; import 'package:plane/provider/profile_provider.dart'; import 'package:plane/provider/projects_provider.dart'; import 'package:plane/provider/search_issue_provider.dart'; +import 'package:plane/provider/states_provider.dart'; import 'package:plane/provider/whats_new_provider.dart'; import 'package:plane/provider/workspace_provider.dart'; +import 'package:plane/repository/states_service.dart'; import 'package:plane/services/shared_preference_service.dart'; import '../repository/dashboard_service.dart'; @@ -98,6 +100,10 @@ class ProviderList { static StateNotifierProvider configProvider = StateNotifierProvider( (ref) => ConfigProvider(ref)); + + static StateNotifierProvider statesProvider = + StateNotifierProvider( + (ref) => StatesProvider(ref, StatesService())); static void clear({required WidgetRef ref}) { ref.read(issueProvider).clear(); diff --git a/lib/provider/states_provider.dart b/lib/provider/states_provider.dart new file mode 100644 index 00000000..53e019c0 --- /dev/null +++ b/lib/provider/states_provider.dart @@ -0,0 +1,185 @@ +import 'dart:developer'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/models/states_model.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/repository/states_service.dart'; +import 'package:plane/utils/enums.dart'; + +final defaultStateGroups = [ + 'backlog', + 'unstarted', + 'started', + 'completed', + 'cancelled', +]; + +class StatesData { + StatesData( + {required this.projectStates, + required this.statesState, + required this.createStateLoading, + required this.updateState, + required this.deleteState, + required this.stateGroups}); + + factory StatesData.initialize() { + return StatesData( + projectStates: {}, + statesState: StateEnum.empty, + createStateLoading: StateEnum.empty, + updateState: StateEnum.empty, + deleteState: StateEnum.empty, + stateGroups: {}); + } + + StatesData copyWith( + {Map? states, + StateEnum? statesState, + StateEnum? createStateLoading, + StateEnum? updateState, + StateEnum? deleteState, + Map>? stateGroups}) { + return StatesData( + projectStates: states ?? projectStates, + statesState: statesState ?? this.statesState, + stateGroups: stateGroups ?? this.stateGroups, + createStateLoading: createStateLoading ?? this.createStateLoading, + updateState: updateState ?? this.updateState, + deleteState: deleteState ?? this.deleteState); + } + + Map projectStates = {}; + Map> stateGroups = {}; + StateEnum statesState = StateEnum.empty; + StateEnum createStateLoading = StateEnum.empty; + StateEnum updateState = StateEnum.empty; + StateEnum deleteState = StateEnum.empty; +} + +class StatesProvider extends StateNotifier { + StatesProvider(this.ref, this.statesService) : super(StatesData.initialize()); + Ref ref; + StatesService statesService; + + Future getStates({required String slug, required String projectId}) async { + state = state.copyWith(statesState: StateEnum.loading); + final states = + await statesService.getStates(slug: slug, projectId: projectId); + states.fold( + (states) { + state = state.copyWith(states: states, statesState: StateEnum.success); + getGroupedStates(); + }, + (err) { + if (err.response!.statusCode == 403) { + state = state.copyWith(statesState: StateEnum.restricted); + } else { + state = state.copyWith(statesState: StateEnum.error); + } + }, + ); + } + + void getGroupedStates() { + state = state.copyWith(stateGroups: { + for (final stateGroup in defaultStateGroups) + stateGroup: state.projectStates.values.where((state) { + return state.group == stateGroup; + }).toList() + }); + } + + Future addState( + {required Map data, + required String slug, + required String projectId}) async { + state = state.copyWith(createStateLoading: StateEnum.loading); + final newState = await statesService.createState( + data: data, slug: slug, projectId: projectId); + newState.fold((addedState) { + final projectStates = state.projectStates; + final newStateGroupData = state.stateGroups; + projectStates.addEntries({addedState.id: addedState}.entries); + newStateGroupData.update( + addedState.group!, + (existingStates) => [...existingStates, addedState], + ifAbsent: () => [addedState], + ); + state = state.copyWith( + stateGroups: newStateGroupData, + states: projectStates, + createStateLoading: StateEnum.success); + }, (err) { + log(err.response.toString()); + state = state.copyWith(createStateLoading: StateEnum.error); + }); + } + + Future updateState({ + required Map data, + required String slug, + required String projectId, + required String stateId, + }) async { + state = state.copyWith(updateState: StateEnum.loading); + final response = await statesService.updateState( + data: data, slug: slug, projectId: projectId, stateId: stateId); + response.fold((updateState) { + final projectStates = state.projectStates; + projectStates[updateState.id] = updateState; + final Map> updatedGroups = { + ...state.stateGroups + }; + final String groupId = updateState.group!; + final List? groupStates = updatedGroups[groupId]; + if (groupStates != null) { + final int indexToUpdate = + groupStates.indexWhere((s) => s.id == updateState.id); + if (indexToUpdate != -1) { + groupStates[indexToUpdate] = updateState; + updatedGroups[groupId] = groupStates; + state = state.copyWith( + states: projectStates, + stateGroups: updatedGroups, + updateState: StateEnum.success); + } + } + }, (err) { + state = state.copyWith(updateState: StateEnum.error); + log(err.response.toString()); + }); + } + + Future deleteState({required String stateId}) async { + state = state.copyWith(deleteState: StateEnum.loading); + final delete = await statesService.deleteState( + slug: ref + .watch(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: ref.watch(ProviderList.projectProvider).currentProject['id'], + stateId: stateId, + ); + + delete.fold((deleted) { + final projectStates = state.projectStates; + projectStates.removeWhere((key, value) => key == stateId); + final Map> updatedGroups = { + ...state.stateGroups + }; + updatedGroups.forEach((groupId, groupStates) { + final int indexToRemove = + groupStates.indexWhere((s) => s.id == stateId); + if (indexToRemove != -1) { + groupStates.removeAt(indexToRemove); + updatedGroups[groupId] = groupStates; + } + }); + state = + state.copyWith(states: projectStates, stateGroups: updatedGroups, deleteState: StateEnum.success); + }, (err) { + state = state.copyWith(deleteState: StateEnum.error); + log(err.response.toString()); + }); + } +} diff --git a/lib/provider/workspace_provider.dart b/lib/provider/workspace_provider.dart index 3b052a02..91e987a3 100644 --- a/lib/provider/workspace_provider.dart +++ b/lib/provider/workspace_provider.dart @@ -88,7 +88,7 @@ class WorkspaceProvider extends ChangeNotifier { try { final response = await DioConfig().dioServe( hasAuth: true, - url: APIs.baseApi + APIs.listWorkspaceInvitaion, + url: APIs.listWorkspaceInvitaion, hasBody: false, httpMethod: HttpMethod.get, ); @@ -111,7 +111,7 @@ class WorkspaceProvider extends ChangeNotifier { try { await DioConfig().dioServe( hasAuth: true, - url: (APIs.joinWorkspace), + url: APIs.listWorkspaceInvitaion, hasBody: true, data: {"invitations": data}, httpMethod: HttpMethod.post, @@ -318,7 +318,6 @@ class WorkspaceProvider extends ChangeNotifier { } selectedWorkspace = WorkspaceModel.fromJson(workspaces[0]); final slug = selectedWorkspace.workspaceSlug; - log('AFTER DELETE WORKSPACE ${selectedWorkspace.workspaceName} }'); ref!.read(ProviderList.dashboardProvider).getDashboard(); projectProv.projects = []; projectProv.getProjects(slug: slug); diff --git a/lib/repository/profile_provider_service.dart b/lib/repository/profile_provider_service.dart index 73aa806c..19d44601 100644 --- a/lib/repository/profile_provider_service.dart +++ b/lib/repository/profile_provider_service.dart @@ -17,7 +17,7 @@ class ProfileService { try { final response = await dio.dioServe( hasAuth: true, - url: '${APIs.baseApi}${APIs.profile}', + url: APIs.profile, hasBody: false, httpMethod: HttpMethod.get, ); @@ -32,7 +32,7 @@ class ProfileService { try { final response = await dio.dioServe( hasAuth: true, - url: '${APIs.baseApi}${APIs.profile}settings/', + url: '${APIs.profile}settings/', hasBody: false, httpMethod: HttpMethod.get, ); diff --git a/lib/repository/states_service.dart b/lib/repository/states_service.dart new file mode 100644 index 00000000..4a146533 --- /dev/null +++ b/lib/repository/states_service.dart @@ -0,0 +1,130 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:plane/config/apis.dart'; +import 'package:plane/models/states_model.dart'; +import 'package:plane/services/dio_service.dart'; +import 'package:plane/utils/enums.dart'; + +class StatesService { + final dio = DioConfig(); + + Future, DioException>> getStates( + {required String slug, required String projectId}) async { + try { + final response = await dio.dioServe( + hasAuth: true, + url: APIs.states + .replaceAll("\$SLUG", slug) + .replaceAll('\$PROJECTID', projectId), + hasBody: false, + httpMethod: HttpMethod.get, + ); + // for (final element in (response.data as List)) { + // final statesModel = StatesModel.fromJson(element); + // statesModel.stateIcon = SvgPicture.asset( + // element['id'] == 'backlog' + // ? 'assets/svg_images/circle.svg' + // : element['id'] == 'cancelled' + // ? 'assets/svg_images/cancelled.svg' + // : element['id'] == 'completed' + // ? 'assets/svg_images/done.svg' + // : element['id'] == 'started' + // ? 'assets/svg_images/in_progress.svg' + // : 'assets/svg_images/unstarted.svg', + // height: 22, + // width: 22, + // colorFilter: int.tryParse( + // "FF${element['color'].toString().replaceAll('#', '')}", + // radix: 16) != + // null + // ? ColorFilter.mode( + // Color( + // int.parse( + // "FF${element['color'].toString().replaceAll('#', '')}", + // radix: 16, + // ), + // ), + // BlendMode.srcIn) + // : null, + // ); + // } + final states = { + for (final state in response.data) + state['id'].toString(): StatesModel.fromJson(state) + }; + return Left(states); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } + + Future> createState( + {required Map data, + required String slug, + required String projectId}) async { + try { + final response = await DioConfig().dioServe( + hasAuth: true, + url: APIs.states + .replaceFirst('\$SLUG', slug) + .replaceFirst('\$PROJECTID', projectId), + hasBody: true, + httpMethod: HttpMethod.post, + data: data); + return Left(StatesModel.fromJson(response.data)); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } + + Future> updateState( + {required Map data, + required String slug, + required String projectId, + required String stateId + }) async { + try { + final response = await DioConfig().dioServe( + hasAuth: true, + url: '${APIs.states + .replaceFirst('\$SLUG', slug) + .replaceFirst('\$PROJECTID', projectId)}$stateId/', + hasBody: true, + httpMethod: HttpMethod.patch, + data: data); + return Left(StatesModel.fromJson(response.data)); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } + + Future> deleteState( + { + required String slug, + required String projectId, + required String stateId + }) async { + try { + final response = await DioConfig().dioServe( + hasAuth: true, + url: '${APIs.states + .replaceFirst('\$SLUG', slug) + .replaceFirst('\$PROJECTID', projectId)}$stateId/', + hasBody: true, + httpMethod: HttpMethod.delete, + ); + return Left(response.data); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } + +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart index e5c58483..22472a66 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart @@ -67,6 +67,7 @@ class _CreateIssueState extends ConsumerState void initCreateIssue() { final prov = ref.read(ProviderList.issuesProvider); final projectProvider = ref.read(ProviderList.projectProvider); + final statesProvider = ref.read(ProviderList.statesProvider.notifier); ref.read(ProviderList.issueProvider).initCookies(); prov.createIssueProjectData = widget.projectId != null ? projectProvider.projects @@ -83,14 +84,13 @@ class _CreateIssueState extends ConsumerState if (widget.fromMyIssues) { prov.statesState = StateEnum.loading; - prov + statesProvider .getStates( - showLoading: false, slug: ref .read(ProviderList.workspaceProvider) .selectedWorkspace .workspaceSlug, - projID: widget.projectId ?? + projectId: widget.projectId ?? ref.read(ProviderList.projectProvider).currentProject['id']) .then((value) { prov.createIssuedata['state'] = @@ -165,6 +165,7 @@ class _CreateIssueState extends ConsumerState final themeProvider = ref.watch(ProviderList.themeProvider); final issuesProvider = ref.watch(ProviderList.issuesProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final statesProvider = ref.watch(ProviderList.statesProvider.notifier); final estimatesProvider = ref.watch(ProviderList.estimatesProvider); final BuildContext baseContext = context; if (issuesProvider.createIssuedata['state'] == null && @@ -176,7 +177,7 @@ class _CreateIssueState extends ConsumerState onWillPop: () async { issuesProvider.createIssuedata = {}; issuesProvider.statesData = tempStatesData; - issuesProvider.states = tempStates; + // issuesProvider.states = tempStates; issuesProvider.stateOrdering = tempStateOrdering; issuesProvider.stateIcons = tempStatesIcons; issuesProvider.labels = tempLabels; @@ -195,7 +196,7 @@ class _CreateIssueState extends ConsumerState onPressed: () { issuesProvider.createIssuedata = {}; issuesProvider.statesData = tempStatesData; - issuesProvider.states = tempStates; + // issuesProvider.states = tempStates; issuesProvider.stateOrdering = tempStateOrdering; issuesProvider.stateIcons = tempStatesIcons; issuesProvider.labels = tempLabels; @@ -270,14 +271,14 @@ class _CreateIssueState extends ConsumerState builder: (ctx) => const SelectProject()).then( (value) { - issuesProvider + statesProvider .getStates( slug: ref .read(ProviderList .workspaceProvider) .selectedWorkspace .workspaceSlug, - projID: issuesProvider + projectId: issuesProvider .createIssueProjectData[ 'id']) .then((value) { @@ -773,20 +774,21 @@ class _CreateIssueState extends ConsumerState issuesProvider .createIssuedata[ 'state']]), - CustomText( - issuesProvider.createIssuedata[ - 'state'] == - null - ? 'Select' - : issuesProvider - .states[issuesProvider - .createIssuedata[ - 'state']]['name'], - type: FontStyle.Small, - color: themeProvider - .themeManager - .primaryTextColor, - ), + // CustomText( + // issuesProvider.createIssuedata[ + // 'state'] == + // null + // ? 'Select' + // : issuesProvider + // .states[issuesProvider + // .createIssuedata[ + // 'state']]['name'], + // type: FontStyle.Small, + // color: themeProvider + // .themeManager + // .primaryTextColor, + // ), + issuesProvider.createIssuedata[ 'state'] == null @@ -1835,7 +1837,7 @@ class _CreateIssueState extends ConsumerState issuesProvider.createIssuedata = {}; issuesProvider.statesData = tempStatesData; - issuesProvider.states = tempStates; + // issuesProvider.states = tempStates; issuesProvider.stateOrdering = tempStateOrdering; issuesProvider.stateIcons = tempStatesIcons; issuesProvider.labels = tempLabels; @@ -1879,14 +1881,14 @@ class _CreateIssueState extends ConsumerState tempAssignees = projectProvider.projectMembers; if (widget.fromMyIssues) { - issuesProvider + statesProvider .getStates( slug: ref .read( ProviderList.workspaceProvider) .selectedWorkspace .workspaceSlug, - projID: widget.projectId ?? + projectId: widget.projectId ?? ref .read(ProviderList .projectProvider) diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart index 2f71bf74..42326926 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart @@ -9,6 +9,7 @@ import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/bottom_sheets/delete_state_sheet.dart'; import 'package:plane/provider/issues_provider.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/provider/states_provider.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; @@ -17,8 +18,6 @@ import 'package:plane/widgets/custom_button.dart'; import 'package:plane/widgets/custom_text.dart'; -List states = ['backlog', 'unstarted', 'started', 'completed', 'cancelled']; - class StatesPage extends ConsumerStatefulWidget { const StatesPage({super.key}); @@ -35,12 +34,13 @@ class _StatesPageState extends ConsumerState { @override Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); - final issuesProvider = ref.watch(ProviderList.issuesProvider); + // final issuesProvider = ref.watch(ProviderList.issuesProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); return Container( color: themeProvider.themeManager.primaryBackgroundDefaultColor, child: ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), - itemCount: states.length, + itemCount: statesProvider.stateGroups.length, itemBuilder: (context, index) { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -49,8 +49,9 @@ class _StatesPageState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ CustomText( - states[index].toString().replaceFirst(states[index][0], - states[index][0].toString().toUpperCase()), + statesProvider.stateGroups.keys + .toList()[index] + .fistLetterToUpper(), // values['group'].replaceFirst(values['group'][0], values['group'][0].toUpperCase()), type: FontStyle.H5, fontWeight: FontWeightt.Medium, @@ -76,9 +77,9 @@ class _StatesPageState extends ConsumerState { ), child: AddUpdateState( groupIndex: index, - stateKey: states[index].toString().replaceFirst( - states[index][0], - states[index][0].toString().toUpperCase()), + stateKey: statesProvider.stateGroups.keys + .toList()[index] + .fistLetterToUpper(), method: CRUD.create, stateId: '', name: '', @@ -95,14 +96,15 @@ class _StatesPageState extends ConsumerState { ) ], ), - issuesProvider.statesData[states[index]] == null + statesProvider.stateGroups.values.toList()[index].isEmpty ? const SizedBox.shrink() : ListView.builder( padding: EdgeInsets.zero, primary: false, shrinkWrap: true, - itemCount: - issuesProvider.statesData[states[index]].length, + itemCount: statesProvider.stateGroups.values + .toList()[index] + .length, itemBuilder: (context, idx) { return Container( margin: const EdgeInsets.only(bottom: 16), @@ -122,18 +124,26 @@ class _StatesPageState extends ConsumerState { Row( children: [ SvgPicture.asset( - states[index] == 'backlog' + statesProvider.stateGroups.keys + .toList()[index] == + 'backlog' ? 'assets/svg_images/circle.svg' - : states[index] == 'cancelled' + : statesProvider.stateGroups.keys + .toList()[index] == + 'cancelled' ? 'assets/svg_images/cancelled.svg' - : states[index] == 'completed' + : statesProvider.stateGroups.keys + .toList()[index] == + 'completed' ? 'assets/svg_images/done.svg' - : states[index] == 'started' + : statesProvider + .stateGroups.keys + .toList()[index] == + 'started' ? 'assets/svg_images/in_progress.svg' : 'assets/svg_images/circle.svg', colorFilter: ColorFilter.mode( - getColorFromIssueProvider( - issuesProvider, index, idx), + getColorFromIssueProvider(index, idx), BlendMode.srcIn), height: 20, width: 20, @@ -144,8 +154,10 @@ class _StatesPageState extends ConsumerState { SizedBox( width: width * 0.6, child: CustomText( - issuesProvider.statesData[states[index]] - [idx]['name'], + statesProvider.stateGroups.values + .toList()[index][idx] + .name + .toString(), overflow: TextOverflow.ellipsis, maxLines: 1, type: FontStyle.Medium, @@ -177,19 +189,25 @@ class _StatesPageState extends ConsumerState { .bottom), child: AddUpdateState( groupIndex: index, - stateKey: issuesProvider - .statesData[states[index]] - [idx]["group"], + stateKey: statesProvider + .stateGroups.keys + .toList()[index], method: CRUD.update, - stateId: issuesProvider - .statesData[states[index]] - [idx]['id'], - name: issuesProvider - .statesData[states[index]] - [idx]['name'], - color: issuesProvider - .statesData[states[index]] - [idx]['color'], + stateId: statesProvider + .stateGroups.values + .toList()[index][idx] + .id + .toString(), + name: statesProvider + .stateGroups.values + .toList()[index][idx] + .name + .toString(), + color: statesProvider + .stateGroups.values + .toList()[index][idx] + .color + .toString(), ), ); }, @@ -203,9 +221,9 @@ class _StatesPageState extends ConsumerState { ), IconButton( onPressed: () { - if (issuesProvider - .statesData[states[index]] - [idx]['default'] == + if (statesProvider.stateGroups.values + .toList()[index][idx] + .isDefault == true) { CustomToast.showToast( context, @@ -213,8 +231,9 @@ class _StatesPageState extends ConsumerState { 'Cannot delete the default state', toastType: ToastType.failure, ); - } else if (issuesProvider - .statesData[states[index]] + } else if (statesProvider + .stateGroups.values + .toList()[index] .length == 1) { CustomToast.showToast( @@ -235,12 +254,16 @@ class _StatesPageState extends ConsumerState { context: context, builder: (context) { return DeleteStateSheet( - stateName: issuesProvider - .statesData[states[index]] - [idx]['name'], - stateId: issuesProvider - .statesData[states[index]] - [idx]['id'], + stateName: statesProvider + .stateGroups.values + .toList()[index][idx] + .name + .toString(), + stateId: statesProvider + .stateGroups.values + .toList()[index][idx] + .id + .toString(), ); }, ); @@ -270,21 +293,19 @@ class _StatesPageState extends ConsumerState { ); } - Color getColorFromIssueProvider( - IssuesProvider issuesProvider, int index, int idx) { + Color getColorFromIssueProvider(int index, int idx) { + final statesProvider = ref.watch(ProviderList.statesProvider); const Color colorToReturnOnApiError = Color.fromARGB(255, 200, 80, 80); final String? colorData = - issuesProvider.statesData[states[index]][idx]['color']; - + statesProvider.stateGroups.values.toList()[index][idx].color; return (colorData == null || colorData[0] != '#') ? colorToReturnOnApiError : Color(int.parse("FF${colorData.replaceAll('#', '')}", radix: 16)); } } -// ignore: must_be_immutable class AddUpdateState extends ConsumerStatefulWidget { - AddUpdateState( + const AddUpdateState( {required this.stateKey, required this.method, required this.groupIndex, @@ -296,7 +317,7 @@ class AddUpdateState extends ConsumerStatefulWidget { final CRUD method; final String stateId; final String name; - int groupIndex; + final int groupIndex; final String color; @override @@ -313,7 +334,7 @@ class _AddUpdateStateState extends ConsumerState { void initState() { super.initState(); nameController.text = widget.name.isNotEmpty ? widget.name : ''; - stateController.text = states[widget.groupIndex]; + stateController.text = widget.stateKey; if (widget.color.isNotEmpty) { colorController.text = widget.color.replaceAll('#', ''); @@ -322,8 +343,6 @@ class _AddUpdateStateState extends ConsumerState { colorsForLabel[Random().nextInt(colorsForLabel.length)] .replaceAll('#', ''); } - - // log(widget.stateKey); } double height = 0.0; @@ -331,7 +350,8 @@ class _AddUpdateStateState extends ConsumerState { Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); final projectProvider = ref.watch(ProviderList.projectProvider); - final issuesProvider = ref.watch(ProviderList.issuesProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); + final statesProviderRead = ref.watch(ProviderList.statesProvider.notifier); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { final box = context.findRenderObject() as RenderBox; height = box.size.height; @@ -479,9 +499,8 @@ class _AddUpdateStateState extends ConsumerState { ? Container() : GestureDetector( onTap: - issuesProvider - .statesData[ - states[widget.groupIndex]] + statesProvider.stateGroups.values + .toList()[widget.groupIndex] .length == 1 ? null @@ -533,23 +552,31 @@ class _AddUpdateStateState extends ConsumerState { height: 50, ), for (int i = 0; - i < states.length; + i < + statesProvider + .stateGroups + .keys + .length; i++) GestureDetector( onTap: () async { setState(() { stateController .text = - states[i]; + statesProvider + .stateGroups + .keys + .toList()[i]; }); Navigator.pop( context); }, child: Container( - padding: const EdgeInsets + padding: + const EdgeInsets .symmetric( - vertical: - 2), + vertical: + 2), child: Column( children: [ Row( @@ -558,22 +585,24 @@ class _AddUpdateStateState extends ConsumerState { .center, children: [ Radio( - activeColor: stateController.text == states[i] + activeColor: stateController.text == statesProvider.stateGroups.keys.toList()[i] ? null : themeProvider.themeManager.primaryColour, - fillColor: stateController.text != states[i] + fillColor: stateController.text != statesProvider.stateGroups.keys.toList()[i] ? MaterialStateProperty.all(themeProvider.themeManager.borderSubtle01Color) : null, visualDensity: VisualDensity.compact, - value: - states[i], + value: statesProvider + .stateGroups + .keys + .toList()[i], groupValue: stateController.text, onChanged: (value) { setState(() { - stateController.text = states[i]; + stateController.text = statesProvider.stateGroups.keys.toList()[i]; }); Navigator.pop(context); }, @@ -583,7 +612,7 @@ class _AddUpdateStateState extends ConsumerState { width * 0.7, child: CustomText( - states[i], + statesProvider.stateGroups.keys.toList()[i], type: FontStyle.Medium, maxLines: @@ -630,7 +659,7 @@ class _AddUpdateStateState extends ConsumerState { Container( margin: const EdgeInsets - .only( + .only( left: 15), width: MediaQuery.of( context) @@ -698,33 +727,65 @@ class _AddUpdateStateState extends ConsumerState { : 'Update State', ontap: () async { if (nameController.text.isNotEmpty) { - await projectProvider.stateCrud( - slug: ref - .watch(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projId: ref - .watch(ProviderList.projectProvider) - .currentProject['id'], - stateId: widget.stateId.isEmpty ? '' : widget.stateId, - method: widget.method, - context: context, - data: { - "name": nameController.text, - "color": '#${colorController.text}', - "group": stateController.text.toLowerCase(), - "description": "" - }, - ref: ref); - issuesProvider.getStates( - slug: ref - .watch(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: ref - .watch(ProviderList.projectProvider) - .currentProject['id'], - ); + if (widget.method == CRUD.create) { + statesProviderRead.addState( + data: { + "name": nameController.text, + "color": '#${colorController.text}', + "group": stateController.text.toLowerCase(), + "description": "" + }, + slug: ref + .watch(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: ref + .watch(ProviderList.projectProvider) + .currentProject['id']); + } else { + statesProviderRead.updateState( + data: { + "name": nameController.text, + "color": '#${colorController.text}', + "group": stateController.text.toLowerCase(), + "description": "" + }, + slug: ref + .watch(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: ref + .watch(ProviderList.projectProvider) + .currentProject['id'], + stateId: widget.stateId); + } + // await projectProvider.stateCrud( + // slug: ref + // .watch(ProviderList.workspaceProvider) + // .selectedWorkspace + // .workspaceSlug, + // projId: ref + // .watch(ProviderList.projectProvider) + // .currentProject['id'], + // stateId: widget.stateId.isEmpty ? '' : widget.stateId, + // method: widget.method, + // context: context, + // data: { + // "name": nameController.text, + // "color": '#${colorController.text}', + // "group": stateController.text.toLowerCase(), + // "description": "" + // }, + // ref: ref); + // statesProviderRead.getStates( + // slug: ref + // .watch(ProviderList.workspaceProvider) + // .selectedWorkspace + // .workspaceSlug, + // projectId: ref + // .watch(ProviderList.projectProvider) + // .currentProject['id'], + // ); } Navigator.of(context).pop(); }, diff --git a/lib/screens/create_view_screen.dart b/lib/screens/create_view_screen.dart index 3287c7ed..b136cb62 100644 --- a/lib/screens/create_view_screen.dart +++ b/lib/screens/create_view_screen.dart @@ -337,7 +337,7 @@ class _CreateViewState extends ConsumerState { child: filterWidget( color: issuesProvider - .states[e]['color'] + .states[e]!.color .toString() .toColor(), icon: SizedBox( @@ -345,8 +345,7 @@ class _CreateViewState extends ConsumerState { width: 15, child: issuesProvider.stateIcons[e]), text: issuesProvider.states[e] - [ - 'name'], + !.name!, ), ) : filterKeys[index] == 'Assignees:' || filterKeys[index] == 'Created By:' From 7d1a48f70f238eaaffece6c4215697e72f6e8af7 Mon Sep 17 00:00:00 2001 From: LAKHAN BAHETI Date: Thu, 18 Jan 2024 12:38:54 +0530 Subject: [PATCH 5/7] chore: labels provider & states instances refactoring --- .gitignore | 2 + integration_test/dashboard_test.dart | 2 +- lib/bottom_sheets/delete_labels_sheet.dart | 17 +- .../delete_leave_project_sheet.dart | 9 +- lib/bottom_sheets/delete_project_sheet.dart | 4 +- lib/bottom_sheets/delete_workspace_sheet.dart | 7 +- lib/bottom_sheets/filters/filter_sheet.dart | 1 + .../filters/filter_sheet_state.dart | 57 ++- .../filters/widgets/labels_filter.dart | 33 +- .../filters/widgets/state_filter.dart | 35 +- lib/bottom_sheets/label_sheet.dart | 24 +- .../project_invite_memebers_sheet.dart | 4 +- lib/bottom_sheets/select_issue_labels.dart | 83 ++-- lib/bottom_sheets/select_states.dart | 12 +- lib/bottom_sheets/views_sheet.dart | 3 - lib/models/Project/Label/label.model.dart | 31 ++ lib/models/Project/State/states_model.dart | 54 +++ .../project-member/project_member.model.dart | 20 + lib/models/Project/project.model.dart | 77 ++++ .../{ => Workspace}/workspace_model.dart | 15 +- lib/models/states_model.dart | 83 ---- lib/provider/cycles_provider.dart | 75 ++-- lib/provider/issue_provider.dart | 4 +- lib/provider/issues_provider.dart | 369 ++++++----------- lib/provider/label_provider.dart | 194 +++++++++ lib/provider/modules_provider.dart | 93 ++--- lib/provider/page_provider.dart | 20 +- lib/provider/projects_provider.dart | 26 +- lib/provider/provider_list.dart | 35 +- lib/provider/states_provider.dart | 45 +- lib/provider/views_provider.dart | 8 +- lib/provider/workspace_provider.dart | 9 +- lib/repository/labels.service.dart | 108 +++++ lib/repository/states_service.dart | 2 +- .../Home/Dashboard/dash_board_screen.dart | 9 +- .../WorkpsaceSettings/invite_members.dart | 5 +- .../IssuesTab/CreateIssue/create_issue.dart | 55 ++- .../ProjectDetail/IssuesTab/issues_tab.dart | 3 +- .../ProjectDetail/PagesTab/page_detail.dart | 7 +- .../ProjectDetail/Settings/create_label.dart | 23 +- .../ProjectDetail/Settings/features_page.dart | 9 +- .../ProjectDetail/Settings/lables_page.dart | 188 ++++----- .../ProjectDetail/Settings/states_pages.dart | 28 +- .../ProjectDetail/ViewsTab/views_detail.dart | 7 +- .../ProjectDetail/archived_issues.dart | 10 +- .../ProjectDetail/project_detail.dart | 9 +- .../widgets/project_detail_appbar.dart | 9 +- .../project_detail_bottom_actions.dart | 9 +- .../widgets/project_detail_root.dart | 4 +- lib/screens/create_state.dart | 14 +- lib/screens/create_view_screen.dart | 384 ++++++++++-------- lib/screens/on_boarding/auth/sign_in.dart | 5 +- lib/utils/bottom_sheet.helper.dart | 2 +- lib/utils/global_functions.dart | 9 +- lib/utils/issues_filter/group_by_issues.dart | 55 ++- .../issues_filter/issue_filter.helper.dart | 14 +- lib/widgets/issue_card_widget.dart | 170 ++------ pubspec.yaml | 7 +- .../dashboard/dash_board_screen_test.dart | 2 +- 59 files changed, 1396 insertions(+), 1202 deletions(-) create mode 100644 lib/models/Project/Label/label.model.dart create mode 100644 lib/models/Project/State/states_model.dart create mode 100644 lib/models/Project/project-member/project_member.model.dart create mode 100644 lib/models/Project/project.model.dart rename lib/models/{ => Workspace}/workspace_model.dart (77%) delete mode 100644 lib/models/states_model.dart create mode 100644 lib/provider/label_provider.dart create mode 100644 lib/repository/labels.service.dart diff --git a/.gitignore b/.gitignore index f3702eab..1854c3ba 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ *.log *.pyc *.swp +*.freezed.dart +*.g.dart .DS_Store .atom/ .buildlog/ diff --git a/integration_test/dashboard_test.dart b/integration_test/dashboard_test.dart index 7091850d..688d0000 100644 --- a/integration_test/dashboard_test.dart +++ b/integration_test/dashboard_test.dart @@ -5,7 +5,7 @@ import 'package:mocktail/mocktail.dart'; import 'package:plane/bottom_sheets/global_search_sheet.dart'; import 'package:plane/bottom_sheets/select_workspace.dart'; import 'package:plane/models/user_profile_model.dart'; -import 'package:plane/models/workspace_model.dart'; +import 'package:plane/models/Workspace/workspace_model.dart'; import 'package:plane/provider/dashboard_provider.dart'; import 'package:plane/provider/global_search_provider.dart'; import 'package:plane/provider/profile_provider.dart'; diff --git a/lib/bottom_sheets/delete_labels_sheet.dart b/lib/bottom_sheets/delete_labels_sheet.dart index db97111b..8f5fd315 100644 --- a/lib/bottom_sheets/delete_labels_sheet.dart +++ b/lib/bottom_sheets/delete_labels_sheet.dart @@ -20,7 +20,7 @@ class DeleteLabelSheet extends ConsumerStatefulWidget { class _DeleteLabelSheetState extends ConsumerState { @override Widget build(BuildContext context) { - final issuesProvider = ref.read(ProviderList.issuesProvider); + final labelNotifier = ref.read(ProviderList.labelProvider.notifier); return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), child: Column( @@ -62,20 +62,7 @@ class _DeleteLabelSheetState extends ConsumerState { padding: const EdgeInsets.only(bottom: 20), child: Button( ontap: () async { - await issuesProvider - .issueLabels( - slug: ref - .watch(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: ref - .watch(ProviderList.projectProvider) - .currentProject['id'], - method: CRUD.delete, - data: {}, - labelId: widget.labelId, - ref: ref) - .then((value) { + await labelNotifier.deleteLabel(widget.labelId).then((value) { ref.read(ProviderList.issuesProvider).filterIssues( slug: ref .watch(ProviderList.workspaceProvider) diff --git a/lib/bottom_sheets/delete_leave_project_sheet.dart b/lib/bottom_sheets/delete_leave_project_sheet.dart index 37a76648..39c1de11 100644 --- a/lib/bottom_sheets/delete_leave_project_sheet.dart +++ b/lib/bottom_sheets/delete_leave_project_sheet.dart @@ -28,6 +28,8 @@ class _DeleteLeaveProjectSheetState Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final profileProvider = ref.watch(ProviderList.profileProvider); + return GestureDetector( onTap: () { FocusScope.of(context).unfocus(); @@ -234,7 +236,8 @@ class _DeleteLeaveProjectSheetState postHogService( eventName: 'LEAVE_PROJECT', properties: widget.data, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); Navigator.of(context) ..pop() ..pop() @@ -260,7 +263,9 @@ class _DeleteLeaveProjectSheetState postHogService( eventName: 'DELETE_PROJECT', properties: widget.data, - ref: ref); + userEmail: + profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); } }); Navigator.of(context) diff --git a/lib/bottom_sheets/delete_project_sheet.dart b/lib/bottom_sheets/delete_project_sheet.dart index cd08b1ce..5829e185 100644 --- a/lib/bottom_sheets/delete_project_sheet.dart +++ b/lib/bottom_sheets/delete_project_sheet.dart @@ -26,6 +26,7 @@ class _DeleteProjectSheetState extends ConsumerState { Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); final projectProviderRead = ref.watch(ProviderList.projectProvider); + final profileProvider = ref.watch(ProviderList.profileProvider); return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), @@ -209,7 +210,8 @@ class _DeleteProjectSheetState extends ConsumerState { postHogService( eventName: 'DELETE_PROJECT', properties: widget.data, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); } }); Navigator.of(context) diff --git a/lib/bottom_sheets/delete_workspace_sheet.dart b/lib/bottom_sheets/delete_workspace_sheet.dart index 96d504a3..3575a0ba 100644 --- a/lib/bottom_sheets/delete_workspace_sheet.dart +++ b/lib/bottom_sheets/delete_workspace_sheet.dart @@ -26,6 +26,7 @@ class _DeleteOrLeaveWorkpaceState extends ConsumerState { Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); final workspaceProvider = ref.watch(ProviderList.workspaceProvider); + final profileProvider = ref.watch(ProviderList.profileProvider); return GestureDetector( onTap: () { FocusScope.of(context).unfocus(); @@ -240,7 +241,8 @@ class _DeleteOrLeaveWorkpaceState extends ConsumerState { properties: { 'WORKSPACE_NAME': widget.workspaceName }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); await ref .watch(ProviderList.profileProvider) .updateProfile(data: { @@ -279,7 +281,8 @@ class _DeleteOrLeaveWorkpaceState extends ConsumerState { properties: { 'WORKSPACE_NAME': widget.workspaceName }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); await ref .watch(ProviderList.profileProvider) .updateProfile(data: { diff --git a/lib/bottom_sheets/filters/filter_sheet.dart b/lib/bottom_sheets/filters/filter_sheet.dart index 7f4fba06..e4d47e72 100644 --- a/lib/bottom_sheets/filters/filter_sheet.dart +++ b/lib/bottom_sheets/filters/filter_sheet.dart @@ -5,6 +5,7 @@ import 'package:calendar_date_picker2/calendar_date_picker2.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:plane/models/Project/State/states_model.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/cycles_provider.dart'; import 'package:plane/provider/modules_provider.dart'; diff --git a/lib/bottom_sheets/filters/filter_sheet_state.dart b/lib/bottom_sheets/filters/filter_sheet_state.dart index 1156ebd1..5827d3e8 100644 --- a/lib/bottom_sheets/filters/filter_sheet_state.dart +++ b/lib/bottom_sheets/filters/filter_sheet_state.dart @@ -64,12 +64,57 @@ class _FilterState { {'icon': Icons.do_disturb_alt_outlined, 'text': 'none', 'color': '#A3A3A3'} ]; - List states = [ - {'id': 'backlog', 'name': 'Backlog', 'color': '#5e6ad2'}, - {'id': 'unstarted', 'name': 'Unstarted', 'color': '#eb5757'}, - {'id': 'started', 'name': 'Started', 'color': '#26b5ce'}, - {'id': 'completed', 'name': 'Completed', 'color': '#f2c94c'}, - {'id': 'cancelled', 'name': 'Cancelled', 'color': '#4cb782'} + List states = [ + StatesModel.initialize().copyWith( + group: 'backlog', + name: 'Backlog', + color: '#5e6ad2', + stateIcon: SvgPicture.asset( + 'assets/svg_images/circle.svg', + color: '#5e6ad2'.toColor(), + height: 20, + width: 20, + )), + StatesModel.initialize().copyWith( + group: 'unstarted', + name: 'Unstarted', + color: '#eb5757', + stateIcon: SvgPicture.asset( + 'assets/svg_images/unstarted.svg', + color: '#eb5757'.toColor(), + height: 20, + width: 20, + )), + StatesModel.initialize().copyWith( + group: 'started', + name: 'Started', + color: '#26b5ce', + stateIcon: SvgPicture.asset( + 'assets/svg_images/in_progress.svg', + color: '#26b5ce'.toColor(), + height: 20, + width: 20, + )), + StatesModel.initialize().copyWith( + group: 'completed', + name: 'Completed', + color: '#f2c94c', + stateIcon: SvgPicture.asset( + 'assets/svg_images/done.svg', + color: '#f2c94c'.toColor(), + height: 20, + width: 20, + )), + StatesModel.initialize().copyWith( + group: 'cancelled', + name: 'Cancelled', + color: '#4cb782', + stateIcon: SvgPicture.asset( + 'assets/svg_images/cancelled.svg', + color: '#4cb782'.toColor(), + height: 20, + width: 20, + )) ]; Filters filters = Filters( diff --git a/lib/bottom_sheets/filters/widgets/labels_filter.dart b/lib/bottom_sheets/filters/widgets/labels_filter.dart index 47821f57..b7e48f6d 100644 --- a/lib/bottom_sheets/filters/widgets/labels_filter.dart +++ b/lib/bottom_sheets/filters/widgets/labels_filter.dart @@ -11,16 +11,14 @@ class _LabelFilter extends ConsumerStatefulWidget { class __LabelFilterState extends ConsumerState<_LabelFilter> { @override Widget build(BuildContext context) { - final ThemeProvider themeProvider = ref.read(ProviderList.themeProvider); - final IssuesProvider issuesProvider = - ref.watch(ProviderList.issuesProvider); - final MyIssuesProvider myIssuesProvider = - ref.watch(ProviderList.myIssuesProvider); + final themeProvider = ref.read(ProviderList.themeProvider); + final labelsProvider = ref.watch(ProviderList.labelProvider); + return CustomExpansionTile( title: 'Labels', child: (widget.state.issueCategory == IssueCategory.myIssues - ? myIssuesProvider.labels - : issuesProvider.labels) + ? labelsProvider.workspaceLabels + : labelsProvider.projectLabels) .isEmpty ? Container( padding: const EdgeInsets.only(left: 25), @@ -31,14 +29,15 @@ class __LabelFilterState extends ConsumerState<_LabelFilter> { ) : Wrap( children: (widget.state.issueCategory == IssueCategory.myIssues - ? myIssuesProvider.labels - : issuesProvider.labels) - .map((e) => GestureDetector( + ? labelsProvider.workspaceLabels + : labelsProvider.projectLabels) + .values + .map((label) => GestureDetector( onTap: () { - if (widget.state.filters.labels.contains(e['id'])) { - widget.state.filters.labels.remove(e['id']); + if (widget.state.filters.labels.contains(label.id)) { + widget.state.filters.labels.remove(label.id); } else { - widget.state.filters.labels.add(e['id']); + widget.state.filters.labels.add(label.id); } widget.state.setState(); }, @@ -46,11 +45,11 @@ class __LabelFilterState extends ConsumerState<_LabelFilter> { ref: ref, icon: CircleAvatar( radius: 5, - backgroundColor: e['color'].toString().toColor()), - text: e['name'], + backgroundColor: label.color.toColor()), + text: label.name, selected: - widget.state.filters.labels.contains(e['id']), - color: widget.state.filters.labels.contains(e['id']) + widget.state.filters.labels.contains(label.id), + color: widget.state.filters.labels.contains(label.id) ? themeProvider.themeManager.primaryColour : themeProvider .themeManager.secondaryBackgroundDefaultColor, diff --git a/lib/bottom_sheets/filters/widgets/state_filter.dart b/lib/bottom_sheets/filters/widgets/state_filter.dart index 8f6fdcb0..d4565b91 100644 --- a/lib/bottom_sheets/filters/widgets/state_filter.dart +++ b/lib/bottom_sheets/filters/widgets/state_filter.dart @@ -19,50 +19,47 @@ class __StateFilterState extends ConsumerState<_StateFilter> { children: (widget.state.issueCategory == IssueCategory.myIssues ? widget.state.states : statesProvider.projectStates.values) - .map((e) { - final String key = widget.state.issueCategory == IssueCategory.myIssues - ? 'id' - : 'group'; + .map((state) { return (widget.state.isArchived && - (e[key] == 'backlog' || - e[key] == 'unstarted' || - e[key] == 'started')) + (state.group == 'backlog' || + state.group == 'unstarted' || + state.group == 'started')) ? Container() : GestureDetector( onTap: () { - if (widget.state.filters.states.contains(e['id'])) { - widget.state.filters.states.remove(e['id']); + if (widget.state.filters.states.contains(state.group)) { + widget.state.filters.states.remove(state.group); } else { - widget.state.filters.states.add(e['id']); + widget.state.filters.states.add(state.group); } widget.state.setState(); }, child: RectangularChip( ref: ref, icon: SvgPicture.asset( - e[key] == 'backlog' + state.group == 'backlog' ? 'assets/svg_images/circle.svg' - : e[key] == 'cancelled' + : state.group == 'cancelled' ? 'assets/svg_images/cancelled.svg' - : e[key] == 'started' + : state.group == 'started' ? 'assets/svg_images/in_progress.svg' - : e[key] == 'completed' + : state.group == 'completed' ? 'assets/svg_images/done.svg' : 'assets/svg_images/unstarted.svg', colorFilter: ColorFilter.mode( - widget.state.filters.states.contains(e['id']) + widget.state.filters.states.contains(state.group) ? (Colors.white) - : e['color'].toString().toColor(), + : state.color.toColor(), BlendMode.srcIn), height: 20, width: 20, ), - text: e['name'], - color: widget.state.filters.states.contains(e['id']) + text: state.name, + color: widget.state.filters.states.contains(state.group) ? themeProvider.themeManager.primaryColour : themeProvider .themeManager.secondaryBackgroundDefaultColor, - selected: widget.state.filters.states.contains(e['id']), + selected: widget.state.filters.states.contains(state.group), ), ); }).toList()), diff --git a/lib/bottom_sheets/label_sheet.dart b/lib/bottom_sheets/label_sheet.dart index 8d9d6573..7fc22250 100644 --- a/lib/bottom_sheets/label_sheet.dart +++ b/lib/bottom_sheets/label_sheet.dart @@ -41,7 +41,7 @@ class _LabelSheetState extends ConsumerState { @override Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); - final issuesProvider = ref.watch(ProviderList.issuesProvider); + final labelProvider = ref.watch(ProviderList.labelProvider); final pageProvider = ref.watch(ProviderList.pageProvider); final workspaceProvider = ref.watch(ProviderList.workspaceProvider); final projectProvider = ref.watch(ProviderList.projectProvider); @@ -84,16 +84,17 @@ class _LabelSheetState extends ConsumerState { ), Container(height: 20), Wrap( - children: issuesProvider.labels.map((label) { - return search.text.toLowerCase().contains( - label["name"].toString().toLowerCase()) || + children: labelProvider.projectLabels.values.map((label) { + return search.text + .toLowerCase() + .contains(label.name.toLowerCase()) || search.text.trim().isEmpty ? GestureDetector( onTap: () { - if (selectedLabels.contains(label["id"])) { - selectedLabels.remove(label["id"]); + if (selectedLabels.contains(label.id)) { + selectedLabels.remove(label.id); } else { - selectedLabels.add(label["id"]); + selectedLabels.add(label.id); } setState(() {}); }, @@ -103,7 +104,7 @@ class _LabelSheetState extends ConsumerState { padding: const EdgeInsets.symmetric( horizontal: 15, vertical: 10), decoration: BoxDecoration( - color: selectedLabels.contains(label["id"]) + color: selectedLabels.contains(label.id) ? themeProvider.themeManager.primaryColour : (themeProvider.themeManager .primaryBackgroundDefaultColor), @@ -118,16 +119,15 @@ class _LabelSheetState extends ConsumerState { children: [ CircleAvatar( radius: 6, - backgroundColor: - label["color"].toString().toColor()), + backgroundColor: label.color.toColor()), const SizedBox( width: 10, ), CustomText( - label["name"], + label.name, type: FontStyle.Small, overrride: true, - color: selectedLabels.contains(label["id"]) + color: selectedLabels.contains(label.id) ? Colors.white : (themeProvider .themeManager.primaryTextColor), diff --git a/lib/bottom_sheets/project_invite_memebers_sheet.dart b/lib/bottom_sheets/project_invite_memebers_sheet.dart index a4306a19..57752db8 100644 --- a/lib/bottom_sheets/project_invite_memebers_sheet.dart +++ b/lib/bottom_sheets/project_invite_memebers_sheet.dart @@ -47,6 +47,7 @@ class _ProjectInviteMembersSheetState final themeProvider = ref.watch(ProviderList.themeProvider); final workspaceProvider = ref.watch(ProviderList.workspaceProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final profileProvider = ref.watch(ProviderList.profileProvider); final BuildContext mainBuildContext = context; return LoadingWidget( loading: projectProvider.projectInvitationState == StateEnum.loading, @@ -333,7 +334,8 @@ class _ProjectInviteMembersSheetState projectProvider.projectDetailModel!.name, 'INVITED_PROJECT_MEMBER': emailController.text }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); //show success snackbar CustomToast.showToast(mainBuildContext, diff --git a/lib/bottom_sheets/select_issue_labels.dart b/lib/bottom_sheets/select_issue_labels.dart index 23b2ab63..d52accd1 100644 --- a/lib/bottom_sheets/select_issue_labels.dart +++ b/lib/bottom_sheets/select_issue_labels.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:loading_indicator/loading_indicator.dart'; +import 'package:plane/models/Project/Label/label.model.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/custom_toast.dart'; @@ -50,6 +51,8 @@ class _SelectIssueLabelsState extends ConsumerState { Widget build(BuildContext context) { final issuesProvider = ref.watch(ProviderList.issuesProvider); final themeProvider = ref.watch(ProviderList.themeProvider); + final labelProvider = ref.watch(ProviderList.labelProvider); + final labelNotifier = ref.read(ProviderList.labelProvider.notifier); return Container( padding: EdgeInsets.only(bottom: bottomSheetConstBottomPadding), height: MediaQuery.of(context).size.height * 0.8, @@ -86,22 +89,25 @@ class _SelectIssueLabelsState extends ConsumerState { ), Container(height: 15), Expanded( - child: issuesProvider.labels.isNotEmpty + child: labelProvider.projectLabels.isNotEmpty ? ListView.builder( - itemCount: issuesProvider.labels.length, + itemCount: labelProvider.projectLabels.length, shrinkWrap: true, itemBuilder: (context, index) { + final labelId = labelProvider.projectLabels.keys + .elementAt(index); + final label = labelProvider.projectLabels.values + .elementAt(index); return InkWell( onTap: () { // setState(() { if (widget.createIssue) { if (issuesProvider.selectedLabels - .contains(issuesProvider.labels[index])) { + .contains(labelId)) { issuesProvider.selectedLabels - .remove(issuesProvider.labels[index]); + .remove(labelId); } else { - issuesProvider.selectedLabels - .add(issuesProvider.labels[index]); + issuesProvider.selectedLabels.add(labelId); } final prov = ref.watch(ProviderList.issuesProvider); @@ -112,43 +118,36 @@ class _SelectIssueLabelsState extends ConsumerState { prov.setsState(); } else { setState(() { - if (issueDetailsLabels.contains( - issuesProvider.labels[index]['id'])) { - issueDetailsLabels.remove( - issuesProvider.labels[index]['id']); + if (issueDetailsLabels.contains(labelId)) { + issueDetailsLabels.remove(labelId); } else { - issueDetailsLabels.add( - issuesProvider.labels[index]['id']); + issueDetailsLabels.add(labelId); } }); } - // }); }, child: Container( padding: const EdgeInsets.symmetric( vertical: 10, ), - margin: - issuesProvider.labels.length == index + 1 - ? const EdgeInsets.only(bottom: 35) - : null, + margin: labelProvider.projectLabels.length == + index + 1 + ? const EdgeInsets.only(bottom: 35) + : null, child: Column( children: [ Row( children: [ CircleAvatar( radius: 8, - backgroundColor: issuesProvider - .labels[index]['color'] - .toString() - .toColor(), + backgroundColor: + label.color.toColor(), ), Container(width: 10), SizedBox( width: width * 0.7, child: CustomText( - issuesProvider.labels[index]['name'] - .toString(), + label.name.toString(), maxLines: 1, overflow: TextOverflow.ellipsis, type: FontStyle.Medium, @@ -160,9 +159,9 @@ class _SelectIssueLabelsState extends ConsumerState { const Spacer(), widget.createIssue ? createIssueSelectedIconsWidget( - issuesProvider.labels[index]) + label) : issueDetailSelectedIconsWidget( - index), + label), const SizedBox(width: 10) ], ), @@ -316,7 +315,7 @@ class _SelectIssueLabelsState extends ConsumerState { ], ), ), - issuesProvider.labelState == StateEnum.loading + labelProvider.labelState == StateEnum.loading ? Center( child: Container( decoration: BoxDecoration( @@ -369,23 +368,12 @@ class _SelectIssueLabelsState extends ConsumerState { message: 'Color is not valid', toastType: ToastType.failure); } else { - await issuesProvider.issueLabels( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: widget.createIssue - ? ref - .read(ProviderList.issuesProvider) - .createIssueProjectData['id'] - : ref - .read(ProviderList.projectProvider) - .currentProject['id'], - data: { - "name": labelContrtoller.text, - "color": "#${colorController.text}" - }, - ref: ref); + await labelNotifier.updateLabel( + { + 'name': labelContrtoller.text, + 'color': colorController.text, + }, + ); setState(() { createNew = false; colorController.clear(); @@ -439,9 +427,9 @@ class _SelectIssueLabelsState extends ConsumerState { ); } - Widget createIssueSelectedIconsWidget(Map data) { + Widget createIssueSelectedIconsWidget(LabelModel label) { var issuesProvider = ref.watch(ProviderList.issuesProvider); - return issuesProvider.selectedLabels.contains(data) + return issuesProvider.selectedLabels.contains(label.id) ? const Icon( Icons.done, color: Color.fromRGBO(8, 171, 34, 1), @@ -449,9 +437,8 @@ class _SelectIssueLabelsState extends ConsumerState { : const SizedBox.shrink(); } - Widget issueDetailSelectedIconsWidget(int idx) { - final issuesProvider = ref.watch(ProviderList.issuesProvider); - return issueDetailsLabels.contains(issuesProvider.labels[idx]['id']) + Widget issueDetailSelectedIconsWidget(LabelModel label) { + return issueDetailsLabels.contains(label.id) ? const Icon( Icons.done, color: Color.fromRGBO(8, 171, 34, 1), diff --git a/lib/bottom_sheets/select_states.dart b/lib/bottom_sheets/select_states.dart index 1837492f..9d7260fd 100644 --- a/lib/bottom_sheets/select_states.dart +++ b/lib/bottom_sheets/select_states.dart @@ -23,9 +23,10 @@ class _SelectStatesState extends ConsumerState { @override void initState() { final prov = ref.read(ProviderList.issuesProvider); - final statesProvider = ref.watch(ProviderList.statesProvider.notifier); - if (prov.states.isEmpty) { - statesProvider.getStates( + final statesNotifier = ref.watch(ProviderList.statesProvider.notifier); + final statesProvider = ref.watch(ProviderList.statesProvider); + if (statesProvider.projectStates.isEmpty) { + statesNotifier.getStates( slug: ref .read(ProviderList.workspaceProvider) .selectedWorkspace @@ -43,7 +44,7 @@ class _SelectStatesState extends ConsumerState { // ? prov.states['state']['id'] // : ''; // log(prov.createIssuedata['state'].toString()); - selectedState = prov.createIssuedata['state'] ?? prov.states.keys.first; + selectedState = prov.createIssuedata['state'] ?? statesProvider.projectStates.keys.first; super.initState(); } @@ -65,6 +66,7 @@ class _SelectStatesState extends ConsumerState { final issuesProvider = ref.watch(ProviderList.issuesProvider); final issueProvider = ref.watch(ProviderList.issueProvider); final themeProvider = ref.watch(ProviderList.themeProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); return WillPopScope( onWillPop: () async { final prov = ref.read(ProviderList.issuesProvider); @@ -293,7 +295,7 @@ class _SelectStatesState extends ConsumerState { ], ), ), - issuesProvider.statesState == StateEnum.loading + statesProvider.statesState == StateEnum.loading ? Container( alignment: Alignment.center, color: Colors.white.withOpacity(0.7), diff --git a/lib/bottom_sheets/views_sheet.dart b/lib/bottom_sheets/views_sheet.dart index fd46ee53..3d681cad 100644 --- a/lib/bottom_sheets/views_sheet.dart +++ b/lib/bottom_sheets/views_sheet.dart @@ -1,8 +1,5 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/models/global_search_modal.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/models/issues.dart'; diff --git a/lib/models/Project/Label/label.model.dart b/lib/models/Project/Label/label.model.dart new file mode 100644 index 00000000..4e19fef6 --- /dev/null +++ b/lib/models/Project/Label/label.model.dart @@ -0,0 +1,31 @@ +// ignore_for_file: non_constant_identifier_names + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'package:plane/models/Project/project.model.dart'; +import 'package:plane/models/Workspace/workspace_model.dart'; +part 'label.model.freezed.dart'; +part 'label.model.g.dart'; + +@freezed +class LabelModel with _$LabelModel { + const factory LabelModel({ + required String id, + required DateTime created_at, + required DateTime updated_at, + required String name, + required String description, + required String color, + required String created_by, + required String updated_by, + required String project, + required ProjectLiteModel project_detail, + required String workspace, + required WorkspaceLiteModel workspace_detail, + String? parent, + required double sort_order, + }) = _LabelModel; + + factory LabelModel.fromJson(Map json) => + _$LabelModelFromJson(json); +} diff --git a/lib/models/Project/State/states_model.dart b/lib/models/Project/State/states_model.dart new file mode 100644 index 00000000..995d8041 --- /dev/null +++ b/lib/models/Project/State/states_model.dart @@ -0,0 +1,54 @@ +// ignore_for_file: non_constant_identifier_names + +import 'package:flutter/material.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'states_model.freezed.dart'; +part 'states_model.g.dart'; + +@freezed +class StatesModel with _$StatesModel { + const factory StatesModel({ + required final String id, + required final String created_at, + required final String updated_at, + required final String name, + required final String? description, + required final String color, + required final String slug, + required final double sequence, + required final String group, + required final bool? is_default, + required final String? external_source, + required final String? external_id, + required final String created_by, + required final String? updated_by, + required final String project, + required final String workspace, + @JsonKey(includeFromJson: false, includeToJson: false) + Widget? stateIcon, + }) = _StatesModel; + + factory StatesModel.fromJson(Map json) => + _$StatesModelFromJson(json); + + factory StatesModel.initialize() { + return const StatesModel( + id: '', + created_at: '', + updated_at: '', + name: '', + description: '', + color: '', + slug: '', + sequence: 0, + group: '', + is_default: false, + external_source: '', + external_id: '', + created_by: '', + updated_by: '', + project: '', + workspace: '', + stateIcon: null); + } +} diff --git a/lib/models/Project/project-member/project_member.model.dart b/lib/models/Project/project-member/project_member.model.dart new file mode 100644 index 00000000..e251cbc2 --- /dev/null +++ b/lib/models/Project/project-member/project_member.model.dart @@ -0,0 +1,20 @@ + +// ignore_for_file: non_constant_identifier_names + +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'project_member.model.freezed.dart'; +part 'project_member.model.g.dart'; + +@freezed +class ProjectMemberLite with _$ProjectMemberLite{ + + const factory ProjectMemberLite({ + required String id, + String? member_avatar, + required String member_display_name, + required String member_id, + })= _ProjectMemberLite; + + factory ProjectMemberLite.fromJson(Map json) => + _$ProjectMemberLiteFromJson(json); +} \ No newline at end of file diff --git a/lib/models/Project/project.model.dart b/lib/models/Project/project.model.dart new file mode 100644 index 00000000..8cfe44e9 --- /dev/null +++ b/lib/models/Project/project.model.dart @@ -0,0 +1,77 @@ +// ignore_for_file: non_constant_identifier_names + +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:plane/models/Project/project-member/project_member.model.dart'; +import 'package:plane/models/Workspace/workspace_model.dart'; +import 'package:plane/utils/enums.dart'; + +part 'project.model.freezed.dart'; +part 'project.model.g.dart'; + +@freezed +class ProjectModel with _$ProjectModel { + const factory ProjectModel({ + required int archive_in, + required int close_in, + required DateTime created_at, + required String created_by, + required String? cover_image, + required bool cycle_view, + required bool issue_views_view, + required bool module_view, + required bool page_view, + required bool inbox_view, + String? default_assigne, + String? default_state, + required String description, + String? emoji, + String? estimate, + IconProp? icon_prop, + required String id, + required String identifier, + required bool is_deployed, + required bool is_favorite, + required bool is_member, + Role? member_role, + required List members, + required String name, + required int network, + String? project_lead, + required int? sort_order, + required int total_cycles, + required int total_members, + required int total_modules, + required DateTime updated_at, + required String updated_by, + required String workspace, + required WorkspaceLiteModel workspace_detail, + }) = _ProjectModel; + + factory ProjectModel.fromJson(Map json) => + _$ProjectModelFromJson(json); +} + +@freezed +class IconProp with _$IconProp { + const factory IconProp({ + required final String name, + required final String color, + }) = _IconProp; + + factory IconProp.fromJson(Map json) => + _$IconPropFromJson(json); +} + +@freezed +class ProjectLiteModel with _$ProjectLiteModel { + const factory ProjectLiteModel({ + required String id, + required String identifier, + required String name, + required String description, + required String emoji, + }) = _ProjectLiteModel; + + factory ProjectLiteModel.fromJson(Map json) => + _$ProjectLiteModelFromJson(json); +} diff --git a/lib/models/workspace_model.dart b/lib/models/Workspace/workspace_model.dart similarity index 77% rename from lib/models/workspace_model.dart rename to lib/models/Workspace/workspace_model.dart index 9f215064..6f4c2c25 100644 --- a/lib/models/workspace_model.dart +++ b/lib/models/Workspace/workspace_model.dart @@ -1,5 +1,7 @@ - +import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:plane/config/config_variables.dart'; +part 'workspace_model.freezed.dart'; +part 'workspace_model.g.dart'; class WorkspaceModel { WorkspaceModel({ @@ -54,3 +56,14 @@ class WorkspaceModel { 'url': workspaceUrl, }; } + +@freezed +class WorkspaceLiteModel with _$WorkspaceLiteModel { + const factory WorkspaceLiteModel({ + required final String id, + required final String name, + required final String slug, + }) = _WorkspaceLiteModel; + factory WorkspaceLiteModel.fromJson(Map json) => + _$WorkspaceLiteModelFromJson(json); +} diff --git a/lib/models/states_model.dart b/lib/models/states_model.dart deleted file mode 100644 index e9da8458..00000000 --- a/lib/models/states_model.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'package:flutter/material.dart'; - -class StatesModel { - StatesModel( - {required this.id, - this.createdAt, - this.updatedAt, - this.name, - this.description, - this.color, - this.slug, - this.sequence, - this.group, - this.isDefault, - this.externalSource, - this.externalId, - this.createdBy, - this.updatedBy, - this.project, - this.workspace, - this.stateIcon}); - - factory StatesModel.fromJson(Map json) { - return StatesModel( - id: json['id'], - createdAt: json['created_at'], - updatedAt: json['updated_at'], - name: json['name'], - description: json['description'], - color: json['color'], - slug: json['slug'], - sequence: json['sequence']?.toDouble(), - group: json['group'], - isDefault: json['default'], - externalSource: json['external_source'], - externalId: json['external_id'], - createdBy: json['created_by'], - updatedBy: json['updated_by'], - project: json['project'], - workspace: json['workspace'], - stateIcon: null); - } - - final String id; - final String? createdAt; - final String? updatedAt; - final String? name; - final String? description; - final String? color; - final String? slug; - final double? sequence; - final String? group; - final bool? isDefault; - final String? externalSource; - final String? externalId; - final String? createdBy; - final String? updatedBy; - final String? project; - final String? workspace; - Widget? stateIcon; - - StatesModel empty() { - return StatesModel( - id: '', - createdAt: '', - updatedAt: '', - name: '', - description: '', - color: '', - slug: '', - sequence: 0, - group: '', - isDefault: false, - externalSource: '', - externalId: '', - createdBy: '', - updatedBy: '', - project: '', - workspace: '', - stateIcon: null - ); - } -} diff --git a/lib/provider/cycles_provider.dart b/lib/provider/cycles_provider.dart index c22eba0d..0751a057 100644 --- a/lib/provider/cycles_provider.dart +++ b/lib/provider/cycles_provider.dart @@ -130,6 +130,7 @@ class CyclesProvider with ChangeNotifier { required WidgetRef ref}) async { final workspaceProvider = ref.watch(ProviderList.workspaceProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final profileProvider = ref.watch(ProviderList.profileProvider); if (query == 'all') { allCyclesState = StateEnum.loading; } else if (query == 'current') { @@ -247,7 +248,8 @@ class CyclesProvider with ChangeNotifier { 'PROJECT_NAME': projectProvider.projectDetailModel!.name, 'CYCLE_ID': response.data['id'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); WidgetsBinding.instance.addPostFrameCallback((_) { notifyListeners(); }); @@ -386,13 +388,15 @@ class CyclesProvider with ChangeNotifier { List initializeBoard() { final themeProvider = ref!.read(ProviderList.themeProvider); final issuesProvider = ref!.read(ProviderList.issuesProvider); + final labelNotifier = ref!.read(ProviderList.labelProvider.notifier); + final statesProvider = ref!.read(ProviderList.statesProvider); int count = 0; // log(issues.groupBY.name); issues.issues = []; issuesResponse = []; final projectMembers = ref!.read(ProviderList.projectProvider).projectMembers; - + for (int j = 0; j < filterIssues.length; j++) { final List items = []; final groupedIssues = filterIssues.values.toList()[j]; @@ -408,19 +412,9 @@ class CyclesProvider with ChangeNotifier { ), ); } - Map label = {}; String userName = ''; - - bool labelFound = false; bool userFound = false; - - for (int i = 0; i < issuesProvider.labels.length; i++) { - if (groupID == issuesProvider.labels[i]['id']) { - label = issuesProvider.labels[i]; - labelFound = true; - break; - } - } + final label = labelNotifier.getLabelById(groupID); for (int i = 0; i < projectMembers.length; i++) { if (groupID == projectMembers[i]['member']['id']) { @@ -437,7 +431,7 @@ class CyclesProvider with ChangeNotifier { var title = issues.groupBY == GroupBY.priority ? groupID : issues.groupBY == GroupBY.state - ? issuesProvider.states[groupID]!.name + ? statesProvider.projectStates[groupID]!.name : groupID; issues.issues.add(BoardListsData( id: groupID, @@ -448,9 +442,8 @@ class CyclesProvider with ChangeNotifier { ? MediaQuery.of(Const.globalKey.currentContext!).size.width : 300, // shrink: shrinkissuesProvider.states[count++], - title: issues.groupBY == GroupBY.labels && labelFound - ? label['name'][0].toString().toUpperCase() + - label['name'].toString().substring(1) + title: issues.groupBY == GroupBY.labels && label != null + ? label.name[0].toUpperCase() + label.name.toString().substring(1) : userFound && (issues.groupBY == GroupBY.createdBY || issues.groupBY == GroupBY.assignees) @@ -670,22 +663,6 @@ class CyclesProvider with ChangeNotifier { 'priority': filterIssues.keys.elementAt(newListIndex) }); newList[newCardIndex] = response.data; - - final List labelDetails = []; - final issuesProvider = ref!.read(ProviderList.issuesProvider); - newList[newCardIndex]['labels'].forEach((element) { - for (int i = 0; i < issuesProvider.labels.length; i++) { - if (issuesProvider.labels[i]['id'] == element) { - labelDetails.add(issuesProvider.labels[i]); - break; - } - } - - // labelDetails.add(labels.firstWhere((e) => e['id'] == element)); - }); - - newList[newCardIndex]['label_details'] = labelDetails; - if (issues.groupBY == GroupBY.priority) { log(newList[newCardIndex]['name']); newList[newCardIndex]['priority'] = @@ -875,14 +852,18 @@ class CyclesProvider with ChangeNotifier { } void applyCycleIssuesView({required WidgetRef ref}) { - final issuesProvider = ref.watch(ProviderList.issuesProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); - final labelIds = issuesProvider.labels.map((e) => e['id']).toList(); + final projectProvider = ref.read(ProviderList.projectProvider); + final statesProvider = ref.read(ProviderList.statesProvider); + + final labelIds = + ref.read(ProviderList.labelProvider.notifier).getLabelIds(); filterIssues = IssueFilterHelper.organizeIssues( cycleIssuesList, issues.groupBY, issues.orderBY, - labels: labelIds, - members: projectProvider.projectMembers, - states: issuesProvider.states); + labelIDs: labelIds, + memberIDs: projectProvider.projectMembers + .map((e) => e['member']['id'].toString()) + .toList(), + states: statesProvider.projectStates); notifyListeners(); } @@ -895,11 +876,13 @@ class CyclesProvider with ChangeNotifier { }) async { cyclesIssueState = StateEnum.loading; notifyListeners(); - final issuesProvider = ref.read(ProviderList.issuesProvider); final projectProvider = ref.read(ProviderList.projectProvider); final statesProvider = ref.read(ProviderList.statesProvider.notifier); + final labelNotifier = ref.read(ProviderList.labelProvider.notifier); + final states = ref.read(ProviderList.statesProvider).projectStates; + if (issues.groupBY == GroupBY.labels) { - issuesProvider.getLabels(slug: slug, projID: projectId); + labelNotifier.getProjectLabels(); } else if (issues.groupBY == GroupBY.createdBY) { projectProvider.getProjectMembers(slug: slug, projId: projectId); } else if (issues.groupBY == GroupBY.state) { @@ -927,9 +910,11 @@ class CyclesProvider with ChangeNotifier { cycleIssuesList = response.data; final organizedIssues = IssueFilterHelper.organizeIssues( cycleIssuesList, issues.groupBY, issues.orderBY, - labels: issuesProvider.labels.map((e) => e['id']).toList(), - members: projectProvider.projectMembers, - states: issuesProvider.states); + labelIDs: labelNotifier.getLabelIds(), + memberIDs: projectProvider.projectMembers + .map((e) => e['member']['id'].toString()) + .toList(), + states: states); filterIssues = organizedIssues; issuesResponse = []; isIssuesEmpty = true; @@ -944,7 +929,7 @@ class CyclesProvider with ChangeNotifier { isIssuesEmpty = filterIssues.values.first.isEmpty; } if (issues.groupBY == GroupBY.state) { - issuesProvider.states.forEach((key, value) { + states.forEach((key, value) { if (issues.filters.states.isEmpty && filterIssues[key] == null) { filterIssues[key] = []; } diff --git a/lib/provider/issue_provider.dart b/lib/provider/issue_provider.dart index 9210a2f5..e05c6c29 100644 --- a/lib/provider/issue_provider.dart +++ b/lib/provider/issue_provider.dart @@ -199,6 +199,7 @@ class IssueProvider with ChangeNotifier { BuildContext? buildContext}) async { final workspaceProvider = refs.watch(ProviderList.workspaceProvider); final projectProvider = refs.watch(ProviderList.projectProvider); + final profileProvider = refs.watch(ProviderList.profileProvider); try { updateIssueState = StateEnum.loading; notifyListeners(); @@ -223,7 +224,8 @@ class IssueProvider with ChangeNotifier { .firstWhere((element) => element['id'] == projID)['name'], 'ISSUE_ID': issueID }, - ref: refs); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); await getIssueDetails(slug: slug, projID: projID, issueID: issueID); await getIssueActivity(slug: slug, projID: projID, issueID: issueID); await ref.read(ProviderList.myIssuesProvider.notifier).getMyIssues( diff --git a/lib/provider/issues_provider.dart b/lib/provider/issues_provider.dart index 213e06ac..9652154c 100644 --- a/lib/provider/issues_provider.dart +++ b/lib/provider/issues_provider.dart @@ -8,10 +8,10 @@ import 'package:intl/intl.dart'; import 'package:plane/config/const.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; -import 'package:plane/models/states_model.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; import 'package:plane/utils/constants.dart'; +import 'package:plane/utils/extensions/string_extensions.dart'; import 'package:plane/utils/global_functions.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/issues_filter/issue_filter.helper.dart'; @@ -26,9 +26,7 @@ import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dar class IssuesProvider extends ChangeNotifier { IssuesProvider(ChangeNotifierProviderRef this.ref); Ref? ref; - StateEnum statesState = StateEnum.empty; StateEnum issueState = StateEnum.empty; - StateEnum labelState = StateEnum.empty; StateEnum orderByState = StateEnum.empty; StateEnum projectViewState = StateEnum.empty; StateEnum issuePropertyState = StateEnum.empty; @@ -62,8 +60,6 @@ class IssuesProvider extends ChangeNotifier { Map createIssueProjectData = {}; List issuesResponse = []; List issuesList = []; - List labels = []; - Map states = {}; Map statesData = {}; // List members = []; Map projectView = {}; @@ -139,8 +135,6 @@ class IssuesProvider extends ChangeNotifier { 'completed', 'cancelled', ]; - List stateOrdering = []; - void clear() { issueView = {}; showEmptyStates = true; @@ -173,8 +167,6 @@ class IssuesProvider extends ChangeNotifier { createIssueParentId = ''; issuesResponse = []; subIssuesIds = []; - labels = []; - states = {}; statesData = {}; projectView = {}; groupByResponse = {}; @@ -216,6 +208,8 @@ class IssuesProvider extends ChangeNotifier { issues.issues = []; final projectMembers = ref!.read(ProviderList.projectProvider).projectMembers; + final labelNotifier = ref!.read(ProviderList.labelProvider.notifier); + final statesProvider = ref!.read(ProviderList.statesProvider); for (int j = 0; j < groupByResponse.length; j++) { final List items = []; final groupedIssues = groupByResponse.values.elementAt(j); @@ -233,20 +227,10 @@ class IssuesProvider extends ChangeNotifier { ), ); } - Map label = {}; String userName = ''; - - bool labelFound = false; + final label = labelNotifier.getLabelById(groupID); bool userFound = false; - for (int i = 0; i < labels.length; i++) { - if (groupID == labels[i]['id']) { - label = labels[i]; - labelFound = true; - break; - } - } - for (int i = 0; i < projectMembers.length; i++) { if (groupID == projectMembers[i]['member']) { userName = projectMembers[i]['member']['display_name']; @@ -266,9 +250,80 @@ class IssuesProvider extends ChangeNotifier { String title = issues.groupBY == GroupBY.priority ? groupID : issues.groupBY == GroupBY.state - ? states[groupID]!.name + ? statesProvider.projectStates[groupID]!.name : groupID; issues.issues.add(BoardListsData( + leading: issues.groupBY == GroupBY.priority + ? title == 'Urgent' + ? Icon( + Icons.error_outline, + size: 18, + color: Color(int.parse("FF${"#EF4444".replaceAll('#', '')}", + radix: 16)), + ) + : title == 'High' + ? Icon( + Icons.signal_cellular_alt, + size: 18, + color: Color(int.parse( + "FF${"#F59E0B".replaceAll('#', '')}", + radix: 16)), + ) + : title == 'Medium' + ? Icon( + Icons.signal_cellular_alt_2_bar, + color: Color(int.parse( + "FF${"#F59E0B".replaceAll('#', '')}", + radix: 16)), + size: 18, + ) + : title == 'Low' + ? Icon( + Icons.signal_cellular_alt_1_bar, + color: Color(int.parse( + "FF${"#22C55E".replaceAll('#', '')}", + radix: 16)), + size: 18, + ) + : Icon( + Icons.do_disturb_alt_outlined, + color: Color(int.parse( + "FF${"#A3A3A3".replaceAll('#', '')}", + radix: 16)), + size: 18, + ) + : issues.groupBY == GroupBY.createdBY || + issues.groupBY == GroupBY.assignees + ? Container( + height: 22, + alignment: Alignment.center, + width: 22, + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Color.fromRGBO(55, 65, 81, 1), + ), + child: CustomText( + title.toString().toUpperCase()[0], + fontSize: 12, + color: Colors.white, + fontWeight: FontWeightt.Medium, + ), + ) + : issues.groupBY == GroupBY.labels + ? Container( + margin: const EdgeInsets.only(top: 3), + height: 15, + alignment: Alignment.center, + width: 15, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: title == 'None' + ? Colors.black + : label?.color.toColor()), + ) + : issues.groupBY == GroupBY.stateGroups + ? defaultStatedetails[groupID]['icon'] + : stateIcons[groupID], id: groupID, items: items, shrink: j >= shrinkStates.length ? false : shrinkStates[j], @@ -277,9 +332,9 @@ class IssuesProvider extends ChangeNotifier { ? MediaQuery.of(Const.globalKey.currentContext!).size.width : (width > 500 ? 400 : width * 0.8), // shrink: shrinkStates[count++], - title: issues.groupBY == GroupBY.labels && labelFound - ? label['name'][0].toString().toUpperCase() + - label['name'].toString().substring(1) + title: issues.groupBY == GroupBY.labels && label != null + ? label.name[0].toString().toUpperCase() + + label.name.toString().substring(1) : userFound && (issues.groupBY == GroupBY.createdBY || issues.groupBY == GroupBY.assignees) @@ -308,78 +363,6 @@ class IssuesProvider extends ChangeNotifier { } for (final element in issues.issues) { - element.leading = issues.groupBY == GroupBY.priority - ? element.title == 'Urgent' - ? Icon( - Icons.error_outline, - size: 18, - color: Color(int.parse("FF${"#EF4444".replaceAll('#', '')}", - radix: 16)), - ) - : element.title == 'High' - ? Icon( - Icons.signal_cellular_alt, - size: 18, - color: Color(int.parse( - "FF${"#F59E0B".replaceAll('#', '')}", - radix: 16)), - ) - : element.title == 'Medium' - ? Icon( - Icons.signal_cellular_alt_2_bar, - color: Color(int.parse( - "FF${"#F59E0B".replaceAll('#', '')}", - radix: 16)), - size: 18, - ) - : element.title == 'Low' - ? Icon( - Icons.signal_cellular_alt_1_bar, - color: Color(int.parse( - "FF${"#22C55E".replaceAll('#', '')}", - radix: 16)), - size: 18, - ) - : Icon( - Icons.do_disturb_alt_outlined, - color: Color(int.parse( - "FF${"#A3A3A3".replaceAll('#', '')}", - radix: 16)), - size: 18, - ) - : issues.groupBY == GroupBY.createdBY || - issues.groupBY == GroupBY.assignees - ? Container( - height: 22, - alignment: Alignment.center, - width: 22, - decoration: const BoxDecoration( - shape: BoxShape.circle, - color: Color.fromRGBO(55, 65, 81, 1), - ), - child: CustomText( - element.title.toString().toUpperCase()[0], - fontSize: 12, - color: Colors.white, - fontWeight: FontWeightt.Medium, - ), - ) - : issues.groupBY == GroupBY.labels - ? Container( - margin: const EdgeInsets.only(top: 3), - height: 15, - alignment: Alignment.center, - width: 15, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: element.title == 'None' ? Colors.black : null - // color: Color(int.parse(element.title)), - ), - ) - : issues.groupBY == GroupBY.stateGroups - ? defaultStatedetails[element.id]['icon'] - : stateIcons[element.id]; - element.header = SizedBox( // margin: const EdgeInsets.only(bottom: 10), height: 50, @@ -476,17 +459,19 @@ class IssuesProvider extends ChangeNotifier { required int newListIndex, required int oldListIndex, }) async { + final newListID = groupByResponse.keys.elementAt(newListIndex); + final oldListID = groupByResponse.keys.elementAt(oldListIndex); try { if (oldListIndex == newListIndex) { notifyListeners(); return; } - (groupByResponse[stateOrdering[newListIndex]] as List).insert( - newCardIndex, - groupByResponse[stateOrdering[oldListIndex]].removeAt(oldCardIndex)); + + groupByResponse[newListID].insert( + newCardIndex, groupByResponse[oldListID].removeAt(oldCardIndex)); updateIssueState = StateEnum.loading; notifyListeners(); - final issue = groupByResponse[stateOrdering[newListIndex]][newCardIndex]; + final issue = groupByResponse[newListID][newCardIndex]; final response = await DioConfig().dioServe( hasAuth: true, url: APIs.issueDetails @@ -496,40 +481,19 @@ class IssuesProvider extends ChangeNotifier { hasBody: true, httpMethod: HttpMethod.patch, data: issues.groupBY == GroupBY.state - ? { - 'state': stateOrdering[newListIndex], - 'priority': issue['priority'] - } + ? {'state': newListID, 'priority': issue['priority']} : { 'state': issue['state'], - 'priority': stateOrdering[newListIndex], + 'priority': newListID, }); - groupByResponse[stateOrdering[newListIndex]][newCardIndex] = - response.data; - - final List labelDetails = []; + groupByResponse[newListID][newCardIndex] = response.data; - groupByResponse[stateOrdering[newListIndex]][newCardIndex]['labels'] - .forEach((element) { - for (int i = 0; i < labels.length; i++) { - if (labels[i]['id'] == element) { - labelDetails.add(labels[i]); - break; - } - } - - // labelDetails.add(labels.firstWhere((e) => e['id'] == element)); - }); - - groupByResponse[stateOrdering[newListIndex]][newCardIndex] - ['label_details'] = labelDetails; updateIssueState = StateEnum.success; if (issues.groupBY == GroupBY.priority) { - groupByResponse[stateOrdering[newListIndex]][newCardIndex]['priority'] = - stateOrdering[newListIndex]; + groupByResponse[newListID][newCardIndex]['priority'] = newListID; } if (issues.orderBY != OrderBY.manual) { - (groupByResponse[stateOrdering[newListIndex]] as List).sort((a, b) { + groupByResponse[newListID].sort((a, b) { if (issues.orderBY == OrderBY.priority) { return priorityParser(a['priority']) .compareTo(priorityParser(b['priority'])); @@ -547,9 +511,8 @@ class IssuesProvider extends ChangeNotifier { notifyListeners(); // ignore: unused_catch_clause } on DioException catch (err) { - (groupByResponse[stateOrdering[oldListIndex]] as List).insert( - oldCardIndex, - groupByResponse[stateOrdering[newListIndex]].removeAt(newCardIndex)); + (groupByResponse[oldListID] as List).insert( + oldCardIndex, groupByResponse[newListID].removeAt(newCardIndex)); // ignore: use_build_context_synchronously CustomToast.showToast(context, @@ -571,94 +534,6 @@ class IssuesProvider extends ChangeNotifier { issues.displayProperties.attachmentCount; } - Future getLabels({required String slug, required String projID}) async { - labelState = StateEnum.loading; - // notifyListeners(); - - try { - final response = await DioConfig().dioServe( - hasAuth: true, - // url: APIs.issueLabels - // .replaceAll("\$SLUG", slug) - // .replaceAll('\$PROJECTID', projID), - url: - '${APIs.baseApi}/api/workspaces/$slug/projects/$projID/issue-labels/', - hasBody: false, - httpMethod: HttpMethod.get, - ); - labels = response.data; - labelState = StateEnum.success; - - notifyListeners(); - } on DioException catch (e) { - log(e.error.toString()); - labelState = StateEnum.error; - notifyListeners(); - } - } - - Future issueLabels( - {required String slug, - required String projID, - required dynamic data, - CRUD? method, - String? labelId, - required WidgetRef ref}) async { - final workspaceProvider = ref.read(ProviderList.workspaceProvider); - final projectProvider = ref.read(ProviderList.projectProvider); - labelState = StateEnum.loading; - notifyListeners(); - final String url = method == CRUD.update || method == CRUD.delete - ? '${APIs.issueLabels.replaceAll("\$SLUG", slug).replaceAll('\$PROJECTID', projID)}$labelId/' - : APIs.issueLabels - .replaceAll("\$SLUG", slug) - .replaceAll('\$PROJECTID', projID); - - try { - final response = await DioConfig().dioServe( - hasAuth: true, - url: url, - hasBody: true, - httpMethod: method == CRUD.update - ? HttpMethod.patch - : method == CRUD.delete - ? HttpMethod.delete - : HttpMethod.post, - data: data); - method != CRUD.read - ? postHogService( - eventName: method == CRUD.create - ? 'ISSUE_LABEL_CREATE' - : method == CRUD.update - ? 'ISSUE_LABEL_UPDATE' - : method == CRUD.delete - ? 'ISSUE_LABEL_DELETE' - : '', - properties: method == CRUD.delete - ? {} - : { - 'WORKSPACE_ID': - workspaceProvider.selectedWorkspace.workspaceId, - 'WORKSPACE_SLUG': - workspaceProvider.selectedWorkspace.workspaceSlug, - 'WORKSPACE_NAME': - workspaceProvider.selectedWorkspace.workspaceName, - 'PROJECT_ID': projectProvider.projectDetailModel!.id, - 'PROJECT_NAME': projectProvider.projectDetailModel!.name, - 'LABEL_ID': response.data['id'] - }, - ref: ref) - : null; - await getLabels(slug: slug, projID: projID); - labelState = StateEnum.success; - notifyListeners(); - } on DioException catch (e) { - log(e.error.toString()); - labelState = StateEnum.error; - notifyListeners(); - } - } - Future createIssue( {required String slug, required String projID, @@ -666,6 +541,7 @@ class IssuesProvider extends ChangeNotifier { required WidgetRef ref}) async { createIssueState = StateEnum.loading; final workspaceProvider = ref.read(ProviderList.workspaceProvider); + final profileProvider = ref.read(ProviderList.profileProvider); notifyListeners(); try { final response = await DioConfig().dioServe( @@ -730,7 +606,8 @@ class IssuesProvider extends ChangeNotifier { .firstWhere((element) => element['id'] == projID)['name'], 'ISSUE_ID': response.data['id'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); // issuesResponse.add(response.data); if (issueCategory == IssueCategory.moduleIssues) { await ref.read(ProviderList.modulesProvider).createModuleIssues( @@ -820,31 +697,6 @@ class IssuesProvider extends ChangeNotifier { } } - Future createState( - {required String slug, - required String projID, - required dynamic data}) async { - statesState = StateEnum.loading; - notifyListeners(); - try { - await DioConfig().dioServe( - hasAuth: true, - url: APIs.states - .replaceAll("\$SLUG", slug) - .replaceAll('\$PROJECTID', projID), - hasBody: true, - httpMethod: HttpMethod.post, - data: data); - ref!.read(ProviderList.statesProvider.notifier).getStates(slug: slug, projectId: projID); - statesState = StateEnum.success; - notifyListeners(); - } on DioException catch (e) { - log(e.response.toString()); - statesState = StateEnum.error; - notifyListeners(); - } - } - Future getIssueDisplayProperties({required Enum issueCategory}) async { final cyclesProvider = ref!.read(ProviderList.cyclesProvider); final modulesProvider = ref!.read(ProviderList.modulesProvider); @@ -1235,10 +1087,15 @@ class IssuesProvider extends ChangeNotifier { void applyIssueView() { final projectMembers = ref!.read(ProviderList.projectProvider).projectMembers; - final labelIds = labels.map((e) => e['id']).toList(); + final labelIds = + ref!.read(ProviderList.labelProvider.notifier).getLabelIds(); + final states = ref!.read(ProviderList.statesProvider).projectStates; groupByResponse = IssueFilterHelper.organizeIssues( issuesList, issues.groupBY, issues.orderBY, - labels: labelIds, members: projectMembers, states: states); + labelIDs: labelIds, + memberIDs: + projectMembers.map((e) => e['member']['id'].toString()).toList(), + states: states); } Future filterIssues({ @@ -1249,22 +1106,23 @@ class IssuesProvider extends ChangeNotifier { Enum issueCategory = IssueCategory.issues, }) async { final projectProvider = ref!.read(ProviderList.projectProvider); + final labelProvider = ref!.read(ProviderList.labelProvider.notifier); + final statesProvider = ref!.read(ProviderList.statesProvider); orderByState = StateEnum.loading; notifyListeners(); if (issues.groupBY == GroupBY.labels) { - getLabels(slug: slug, projID: projID); + labelProvider.getProjectLabels(); } else if (issues.groupBY == GroupBY.createdBY) { projectProvider.getProjectMembers( slug: slug, projId: projID, ); } else if (issues.groupBY == GroupBY.state) { - ref!.read(ProviderList.statesProvider.notifier). - getStates( - slug: slug, - projectId: projID, - ); + ref!.read(ProviderList.statesProvider.notifier).getStates( + slug: slug, + projectId: projID, + ); } String url; @@ -1290,11 +1148,14 @@ class IssuesProvider extends ChangeNotifier { httpMethod: HttpMethod.get, ); issuesList = response.data; + final projectLabelIds = labelProvider.getLabelIds(); final organizedIssues = IssueFilterHelper.organizeIssues( issuesList, issues.groupBY, issues.orderBY, - labels: labels.map((e) => e['id']).toList(), - members: projectProvider.projectMembers, - states: states); + labelIDs: projectLabelIds, + memberIDs: projectProvider.projectMembers + .map((e) => e['member']['id'].toString()) + .toList(), + states: statesProvider.projectStates); if (issueCategory == IssueCategory.issues) { groupByResponse = organizedIssues; } else if (issueCategory == IssueCategory.cycleIssues || diff --git a/lib/provider/label_provider.dart b/lib/provider/label_provider.dart new file mode 100644 index 00000000..fa519481 --- /dev/null +++ b/lib/provider/label_provider.dart @@ -0,0 +1,194 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/models/Project/Label/label.model.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/repository/labels.service.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/utils/global_functions.dart'; + +class LabelState { + // Properties + StateEnum labelState = StateEnum.empty; + Map projectLabels = {}; + Map workspaceLabels = {}; + + // Constructor + LabelState({ + required this.projectLabels, + required this.workspaceLabels, + required this.labelState, + }); + + // CopyWith + LabelState copyWith( + {StateEnum? labelState, + Map? projectLabels, + Map? workspaceLabels}) { + return LabelState( + labelState: labelState ?? this.labelState, + projectLabels: projectLabels ?? this.projectLabels, + workspaceLabels: workspaceLabels ?? this.workspaceLabels); + } + + // Initialize with empty states + factory LabelState.initialize() { + return LabelState( + projectLabels: {}, workspaceLabels: {}, labelState: StateEnum.empty); + } +} + +class LabelNotifier extends StateNotifier { + LabelNotifier(this.ref, this._labelsService) : super(LabelState.initialize()); + // Ref for accessing other providers + final Ref ref; + // Labels Service + final LabelsService _labelsService; + + // Get Label by Id + LabelModel? getLabelById(String id) { + return state.projectLabels[id]; + } + + // Get List of Label IDs I + List getLabelIds() { + return state.projectLabels.keys.toList(); + } + + // Get Project Labels + Future getProjectLabels() async { + state = state.copyWith(labelState: StateEnum.loading); + final projectID = + ref.read(ProviderList.projectProvider).currentProject['id']; + final slug = ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug; + final response = await _labelsService.getProjectLabels(slug, projectID); + response.fold( + (labels) { + state = state.copyWith( + projectLabels: labels, labelState: StateEnum.success); + }, + (err) { + state = state.copyWith(labelState: StateEnum.error); + }, + ); + } + + // Get Workspace Labels + Future getWorkspaceLabels() async { + state = state.copyWith(labelState: StateEnum.loading); + final slug = ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug; + final response = await _labelsService.getProjectLabels(slug, ''); + response.fold( + (labels) { + state = state.copyWith( + workspaceLabels: labels, labelState: StateEnum.success); + }, + (err) { + state = state.copyWith(labelState: StateEnum.error); + }, + ); + } + + // Create Label + Future createLabel(Map payload) async { + state = state.copyWith(labelState: StateEnum.loading); + final slug = ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug; + final projectID = + ref.read(ProviderList.projectProvider).currentProject['id']; + final response = await _labelsService.createLabel(slug, projectID, payload); + response.fold( + (label) { + state = state.copyWith(projectLabels: { + ...state.projectLabels, + label.id: label, + }, labelState: StateEnum.success); + sendPostHogEvent(method: CRUD.create, labelID: label.id); + }, + (err) { + state = state.copyWith(labelState: StateEnum.error); + }, + ); + } + + // Update Label + Future updateLabel(Map payload) async { + state = state.copyWith(labelState: StateEnum.loading); + final slug = ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug; + final projectID = + ref.read(ProviderList.projectProvider).currentProject['id']; + final response = await _labelsService.updateLabel(slug, projectID, payload); + response.fold( + (label) { + final projectLabels = state.projectLabels; + projectLabels[label.id] = LabelModel.fromJson({ + ...projectLabels[label.id]!.toJson(), + ...label.toJson(), + }); + state = state.copyWith( + projectLabels: projectLabels, labelState: StateEnum.success); + sendPostHogEvent(method: CRUD.update, labelID: label.id); + }, + (err) { + state = state.copyWith(labelState: StateEnum.error); + }, + ); + } + + // Delete Label + Future deleteLabel(String labelID) async { + state = state.copyWith(labelState: StateEnum.loading); + final slug = ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug; + final projectID = + ref.read(ProviderList.projectProvider).currentProject['id']; + final response = await _labelsService.deleteLabel(slug, projectID, labelID); + response.fold( + (label) { + state = state.copyWith( + projectLabels: state.projectLabels..remove(labelID), + labelState: StateEnum.success); + }, + (err) { + state = state.copyWith(labelState: StateEnum.error); + }, + ); + sendPostHogEvent(method: CRUD.delete, labelID: labelID); + } + + // SEND POSTHOG EVENT + void sendPostHogEvent({required CRUD method, required String labelID}) { + final workspaceProvider = ref.read(ProviderList.workspaceProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + final profileProvider = ref.read(ProviderList.profileProvider); + postHogService( + eventName: method == CRUD.create + ? 'ISSUE_LABEL_CREATE' + : method == CRUD.update + ? 'ISSUE_LABEL_UPDATE' + : method == CRUD.delete + ? 'ISSUE_LABEL_DELETE' + : '', + properties: { + 'WORKSPACE_ID': workspaceProvider.selectedWorkspace.workspaceId, + 'WORKSPACE_SLUG': workspaceProvider.selectedWorkspace.workspaceSlug, + 'WORKSPACE_NAME': workspaceProvider.selectedWorkspace.workspaceName, + 'PROJECT_ID': projectProvider.projectDetailModel!.id, + 'PROJECT_NAME': projectProvider.projectDetailModel!.name, + 'LABEL_ID': labelID + }, + userEmail: profileProvider.userProfile.email ?? '', + userID: profileProvider.userProfile.id ?? ''); + } +} diff --git a/lib/provider/modules_provider.dart b/lib/provider/modules_provider.dart index bee97c72..43a01a30 100644 --- a/lib/provider/modules_provider.dart +++ b/lib/provider/modules_provider.dart @@ -1,7 +1,5 @@ // ignore_for_file: use_build_context_synchronously - import 'dart:developer'; - import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -19,7 +17,6 @@ import 'package:plane/utils/global_functions.dart'; import 'package:plane/utils/issues_filter/issue_filter.helper.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; - import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; class ModuleProvider with ChangeNotifier { @@ -152,8 +149,9 @@ class ModuleProvider with ChangeNotifier { String? moduleId, required WidgetRef ref}) async { createModuleState = StateEnum.loading; - final workspaceProvider = ref.watch(ProviderList.workspaceProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); + final workspaceProvider = ref.read(ProviderList.workspaceProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + final profileProvider = ref.read(ProviderList.profileProvider); notifyListeners(); try { final response = await DioConfig().dioServe( @@ -176,7 +174,8 @@ class ModuleProvider with ChangeNotifier { 'PROJECT_NAME': projectProvider.projectDetailModel!.name, 'MODULE_ID': response.data['id'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); getModules(slug: slug, projId: projId); createModule.clear(); notifyListeners(); @@ -195,8 +194,9 @@ class ModuleProvider with ChangeNotifier { required Map data, bool disableLoading = false, required WidgetRef ref}) async { - final workspaceProvider = ref.watch(ProviderList.workspaceProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); + final workspaceProvider = ref.read(ProviderList.workspaceProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + final profileProvider = ref.read(ProviderList.profileProvider); if (!disableLoading) { moduleDetailState = StateEnum.loading; notifyListeners(); @@ -222,7 +222,8 @@ class ModuleProvider with ChangeNotifier { 'PROJECT_NAME': projectProvider.projectDetailModel!.name, 'MODULE_ID': response.data['id'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); getModuleDetails( slug: slug, projId: projId, @@ -402,14 +403,18 @@ class ModuleProvider with ChangeNotifier { } void applyModuleIssuesView({required WidgetRef ref}) { - final issuesProvider = ref.read(ProviderList.issuesProvider); - final labelIds = issuesProvider.labels.map((e) => e['id']).toList(); - final projectProvider = ref.watch(ProviderList.projectProvider); + final labelIds = + ref.read(ProviderList.labelProvider.notifier).getLabelIds(); + final projectMembers = + ref.read(ProviderList.projectProvider).projectMembers; + + final states = ref.read(ProviderList.statesProvider).projectStates; filterIssues = IssueFilterHelper.organizeIssues( moduleIssuesList, issues.groupBY, issues.orderBY, - labels: labelIds, - members: projectProvider.projectMembers, - states: issuesProvider.states); + labelIDs: labelIds, + memberIDs: + projectMembers.map((e) => e['member']['id'].toString()).toList(), + states: states); notifyListeners(); } @@ -422,11 +427,13 @@ class ModuleProvider with ChangeNotifier { }) async { moduleIssueState = StateEnum.loading; notifyListeners(); - final issuesProvider = ref.watch(ProviderList.issuesProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); - final statesProvider = ref.watch(ProviderList.statesProvider.notifier); + final projectProvider = ref.read(ProviderList.projectProvider); + final statesProvider = ref.read(ProviderList.statesProvider.notifier); + final labelNotifier = ref.read(ProviderList.labelProvider.notifier); + + final states = ref.read(ProviderList.statesProvider).projectStates; if (issues.groupBY == GroupBY.labels) { - issuesProvider.getLabels(slug: slug, projID: projectId); + labelNotifier.getProjectLabels(); } else if (issues.groupBY == GroupBY.createdBY) { projectProvider.getProjectMembers(slug: slug, projId: projectId); } else if (issues.groupBY == GroupBY.state) { @@ -454,9 +461,11 @@ class ModuleProvider with ChangeNotifier { moduleIssuesList = response.data.values.toList(); final organizedIssues = IssueFilterHelper.organizeIssues( moduleIssuesList, issues.groupBY, issues.orderBY, - labels: issuesProvider.labels.map((e) => e['id']).toList(), - members: projectProvider.projectMembers, - states: issuesProvider.states); + labelIDs: labelNotifier.getLabelIds(), + memberIDs: projectProvider.projectMembers + .map((e) => e['member']['id'].toString()) + .toList(), + states: states); filterIssues = organizedIssues; issuesResponse = []; isIssuesEmpty = true; @@ -471,7 +480,7 @@ class ModuleProvider with ChangeNotifier { isIssuesEmpty = filterIssues.values.first.isEmpty; } if (issues.groupBY == GroupBY.state) { - issuesProvider.states.forEach((key, value) { + states.forEach((key, value) { if (issues.filters.states.isEmpty && filterIssues[key] == null) { filterIssues[key] = []; } @@ -498,6 +507,7 @@ class ModuleProvider with ChangeNotifier { final themeProvider = ref!.read(ProviderList.themeProvider); final issuesProvider = ref!.read(ProviderList.issuesProvider); final projectProvider = ref!.read(ProviderList.projectProvider); + final states = ref!.read(ProviderList.statesProvider).projectStates; int count = 0; // log(issues.groupBY.name); issues.issues = []; @@ -517,19 +527,10 @@ class ModuleProvider with ChangeNotifier { ), ); } - Map label = {}; String userName = ''; - - bool labelFound = false; bool userFound = false; - - for (int i = 0; i < issuesProvider.labels.length; i++) { - if (groupID == issuesProvider.labels[i]['id']) { - label = issuesProvider.labels[i]; - labelFound = true; - break; - } - } + final label = + ref!.read(ProviderList.labelProvider.notifier).getLabelById(groupID); for (int i = 0; i < projectProvider.projectMembers.length; i++) { if (groupID == projectProvider.projectMembers[i]['member']['id']) { @@ -546,7 +547,7 @@ class ModuleProvider with ChangeNotifier { var title = issues.groupBY == GroupBY.priority ? groupID : issues.groupBY == GroupBY.state - ? issuesProvider.states[groupID]!.name + ? states[groupID]!.name : groupID; issues.issues.add(BoardListsData( id: groupID, @@ -557,9 +558,8 @@ class ModuleProvider with ChangeNotifier { ? MediaQuery.of(Const.globalKey.currentContext!).size.width : 300, // shrink: shrinkissuesProvider.states[count++], - title: issues.groupBY == GroupBY.labels && labelFound - ? label['name'][0].toString().toUpperCase() + - label['name'].toString().substring(1) + title: issues.groupBY == GroupBY.labels && label != null + ? label.name[0].toUpperCase() + label.name.substring(1) : userFound && (issues.groupBY == GroupBY.createdBY || issues.groupBY == GroupBY.assignees) @@ -776,23 +776,6 @@ class ModuleProvider with ChangeNotifier { }); filterIssues[stateOrdering[newListIndex]][newCardIndex] = response.data; - final List labelDetails = []; - final issuesProvider = ref!.read(ProviderList.issuesProvider); - filterIssues[stateOrdering[newListIndex]][newCardIndex]['labels'] - .forEach((element) { - for (int i = 0; i < issuesProvider.labels.length; i++) { - if (issuesProvider.labels[i]['id'] == element) { - labelDetails.add(issuesProvider.labels[i]); - break; - } - } - - // labelDetails.add(labels.firstWhere((e) => e['id'] == element)); - }); - - filterIssues[stateOrdering[newListIndex]][newCardIndex]['label_details'] = - labelDetails; - if (issues.groupBY == GroupBY.priority) { log(filterIssues[stateOrdering[newListIndex]][newCardIndex]['name']); filterIssues[stateOrdering[newListIndex]][newCardIndex]['priority'] = diff --git a/lib/provider/page_provider.dart b/lib/provider/page_provider.dart index 8bef8380..2a0565e8 100644 --- a/lib/provider/page_provider.dart +++ b/lib/provider/page_provider.dart @@ -69,6 +69,7 @@ class PageProvider with ChangeNotifier { required String projectId}) async { final workspaceProvider = ref.watch(ProviderList.workspaceProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final profileProvider = ref.watch(ProviderList.profileProvider); try { if (httpMethod != HttpMethod.get || httpMethod == HttpMethod.delete) { if (httpMethod == HttpMethod.delete) { @@ -130,7 +131,8 @@ class PageProvider with ChangeNotifier { 'PAGE_ID': pageID, 'BLOCK_ID': res.data['id'] }, - ref: ref) + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!) : null; if (httpMethod == HttpMethod.delete) { blocks.removeWhere((element) => element['id'] == blockID); @@ -241,8 +243,9 @@ class PageProvider with ChangeNotifier { bool? fromDispose = false}) async { blockSheetState = StateEnum.loading; notifyListeners(); - final workspaceProvider = ref.watch(ProviderList.workspaceProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); + final workspaceProvider = ref.read(ProviderList.workspaceProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + final profileProvider = ref.read(ProviderList.profileProvider); try { final res = await DioConfig().dioServe( httpMethod: HttpMethod.patch, @@ -261,7 +264,8 @@ class PageProvider with ChangeNotifier { 'PROJECT_NAME': projectProvider.projectDetailModel!.name, 'PAGE_ID': res.data['id'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); final int index = pages[selectedFilter]! .indexWhere((element) => element["id"] == pageId); pagesListState = StateEnum.success; @@ -338,8 +342,9 @@ class PageProvider with ChangeNotifier { required WidgetRef ref}) async { pagesListState = StateEnum.loading; setState(); - final workspaceProvider = ref.watch(ProviderList.workspaceProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); + final workspaceProvider = ref.read(ProviderList.workspaceProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + final profileProvider = ref.read(ProviderList.profileProvider); try { final response = await DioConfig().dioServe( httpMethod: HttpMethod.post, @@ -358,7 +363,8 @@ class PageProvider with ChangeNotifier { 'PROJECT_NAME': projectProvider.projectDetailModel!.name, 'PAGE_ID': response.data['id'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); updatepageList( slug: slug, projectId: projectId, diff --git a/lib/provider/projects_provider.dart b/lib/provider/projects_provider.dart index 34e37029..8570d19a 100644 --- a/lib/provider/projects_provider.dart +++ b/lib/provider/projects_provider.dart @@ -13,7 +13,6 @@ import 'package:plane/config/apis.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/global_functions.dart'; - import '../models/issues.dart'; class ProjectsProvider extends ChangeNotifier { @@ -87,7 +86,7 @@ class ProjectsProvider extends ChangeNotifier { {Filters? filters, bool fromViews = false, required WidgetRef ref}) async { - final prov = ref.read(ProviderList.issuesProvider); + final issuesProv = ref.read(ProviderList.issuesProvider); final moduleProv = ref.read(ProviderList.modulesProvider); final viewsProvider = ref.read(ProviderList.viewsProvider.notifier); final intergrationProvider = ref.read(ProviderList.integrationProvider); @@ -112,12 +111,12 @@ class ProjectsProvider extends ChangeNotifier { slug: workspaceSlug, projID: currentProject['id'], ); - prov.getIssueDisplayProperties(issueCategory: IssueCategory.issues); - prov.getProjectView().then((value) { + issuesProv.getIssueDisplayProperties(issueCategory: IssueCategory.issues); + issuesProv.getProjectView().then((value) { if (filters != null) { - prov.issues.filters = filters; + issuesProv.issues.filters = filters; } - prov.filterIssues( + issuesProv.filterIssues( fromViews: fromViews, slug: workspaceSlug, projID: currentProject['id'], @@ -130,7 +129,8 @@ class ProjectsProvider extends ChangeNotifier { ); viewsProvider.getViews(); - prov.getLabels(slug: workspaceSlug, projID: currentProject['id']); + // Fetching labels + ref.read(ProviderList.labelProvider.notifier).getProjectLabels(); getProjectDetails(slug: workspaceSlug, projId: currentProject['id']); @@ -345,7 +345,8 @@ class ProjectsProvider extends ChangeNotifier { WidgetRef? ref, BuildContext? context}) async { createProjectState = StateEnum.loading; - final workspaceProvider = ref!.watch(ProviderList.workspaceProvider); + final workspaceProvider = ref!.read(ProviderList.workspaceProvider); + final profileProvider = ref.read(ProviderList.profileProvider); notifyListeners(); try { final response = await DioConfig().dioServe( @@ -364,7 +365,8 @@ class ProjectsProvider extends ChangeNotifier { 'PROJECT_ID': response.data['id'], 'PROJECT_NAME': response.data['name'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); await getProjects(slug: slug); createProjectState = StateEnum.success; notifyListeners(); @@ -439,7 +441,8 @@ class ProjectsProvider extends ChangeNotifier { required Map data, required WidgetRef ref}) async { updateProjectState = StateEnum.loading; - final workspaceProvider = ref.watch(ProviderList.workspaceProvider); + final workspaceProvider = ref.read(ProviderList.workspaceProvider); + final profileProvider = ref.read(ProviderList.profileProvider); notifyListeners(); log("${APIs.listProjects.replaceAll('\$SLUG', slug)}$projId/"); try { @@ -481,7 +484,8 @@ class ProjectsProvider extends ChangeNotifier { 'PROJECT_ID': response.data['id'], 'PROJECT_NAME': response.data['name'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); notifyListeners(); } on DioException catch (e) { log(e.toString()); diff --git a/lib/provider/provider_list.dart b/lib/provider/provider_list.dart index f60e2a52..8e2dc9f9 100644 --- a/lib/provider/provider_list.dart +++ b/lib/provider/provider_list.dart @@ -10,6 +10,7 @@ import 'package:plane/provider/dashboard_provider.dart'; import 'package:plane/provider/file_upload_provider.dart'; import 'package:plane/provider/global_search_provider.dart'; import 'package:plane/provider/issue_provider.dart'; +import 'package:plane/provider/label_provider.dart'; import 'package:plane/provider/my_issues_provider.dart'; import 'package:plane/provider/page_provider.dart'; import 'package:plane/provider/notification_provider.dart'; @@ -20,8 +21,8 @@ import 'package:plane/provider/states_provider.dart'; import 'package:plane/provider/whats_new_provider.dart'; import 'package:plane/provider/workspace_provider.dart'; import 'package:plane/repository/states_service.dart'; +import 'package:plane/repository/labels.service.dart'; import 'package:plane/services/shared_preference_service.dart'; - import '../repository/dashboard_service.dart'; import '../repository/profile_provider_service.dart'; import '../repository/workspace_service.dart'; @@ -35,68 +36,88 @@ import 'theme_provider.dart'; import 'views_provider.dart'; class ProviderList { + // Auth Provider static final authProvider = ChangeNotifierProvider((ref) => AuthProvider(ref)); + // Profile Provider static ChangeNotifierProvider profileProvider = ChangeNotifierProvider( (_) => ProfileProvider(profileService: ProfileService(DioConfig()))); + // Workspace Provider static ChangeNotifierProvider workspaceProvider = ChangeNotifierProvider((ref) => WorkspaceProvider( ref: ref, workspaceService: WorkspaceService(DioConfig()))); + // Theme Provider static ChangeNotifierProvider themeProvider = ChangeNotifierProvider((ref) => ThemeProvider(ref)); + // Project Provider static ChangeNotifierProvider projectProvider = ChangeNotifierProvider((ref) => ProjectsProvider(ref)); + // File Upload Provider static ChangeNotifierProvider fileUploadProvider = ChangeNotifierProvider( (ref) => FileUploadProvider(ref)); + // Issues Provider static ChangeNotifierProvider issuesProvider = ChangeNotifierProvider((ref) => IssuesProvider(ref)); + // Issue Provider static ChangeNotifierProvider issueProvider = ChangeNotifierProvider((ref) => IssueProvider(ref)); + // Search Issue Provider static ChangeNotifierProvider searchIssueProvider = ChangeNotifierProvider((_) => SearchIssueProvider()); + // Bottom Nav Provider static ChangeNotifierProvider bottomNavProvider = ChangeNotifierProvider((_) => BottomNavProvider()); + // Cycles Provider static ChangeNotifierProvider cyclesProvider = ChangeNotifierProvider((ref) => CyclesProvider(ref)); - + // Modules Provider static ChangeNotifierProvider modulesProvider = ChangeNotifierProvider((ref) => ModuleProvider(ref)); + // Estimates Provider static ChangeNotifierProvider estimatesProvider = ChangeNotifierProvider((_) => EstimatesProvider()); + // My Issues Provider static ChangeNotifierProvider myIssuesProvider = ChangeNotifierProvider((ref) => MyIssuesProvider(ref)); + // Activity Provider static ChangeNotifierProvider activityProvider = ChangeNotifierProvider((_) => ActivityProvider()); + // Dashboard Provider static ChangeNotifierProvider dashboardProvider = ChangeNotifierProvider((ref) => DashBoardProvider( ref: ref, dashboardService: DashboardService(DioConfig()))); + // Integration Provider static ChangeNotifierProvider integrationProvider = ChangeNotifierProvider( (ref) => IntegrationProvider(ref)); + // Views Provider static StateNotifierProvider viewsProvider = StateNotifierProvider( (ref) => ViewsNotifier(ref)); + // Global Search Provider static StateNotifierProvider globalSearchProvider = StateNotifierProvider( (ref) => GlobalSearchProvider(ref)); + // Page Provider static ChangeNotifierProvider pageProvider = ChangeNotifierProvider((ref) => PageProvider()); - + // Notification Provider static ChangeNotifierProvider notificationProvider = ChangeNotifierProvider( (ref) => NotificationProvider(ref)); + // Member Profile Provider static StateNotifierProvider memberProfileProvider = StateNotifierProvider( (ref) => MemberProfileProvider(ref)); - + // Whats New Provider static StateNotifierProvider whatsNewProvider = StateNotifierProvider( (ref) => WhatsNewNotifier(WhatsNew(null))); - + // Config Provider static StateNotifierProvider configProvider = StateNotifierProvider( (ref) => ConfigProvider(ref)); @@ -104,6 +125,10 @@ class ProviderList { static StateNotifierProvider statesProvider = StateNotifierProvider( (ref) => StatesProvider(ref, StatesService())); + // Label Provider + static StateNotifierProvider labelProvider = + StateNotifierProvider( + (ref) => LabelNotifier(ref, LabelsService())); static void clear({required WidgetRef ref}) { ref.read(issueProvider).clear(); diff --git a/lib/provider/states_provider.dart b/lib/provider/states_provider.dart index 53e019c0..29dfd534 100644 --- a/lib/provider/states_provider.dart +++ b/lib/provider/states_provider.dart @@ -1,6 +1,6 @@ import 'dart:developer'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/models/states_model.dart'; +import 'package:plane/models/Project/State/states_model.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/repository/states_service.dart'; import 'package:plane/utils/enums.dart'; @@ -89,10 +89,13 @@ class StatesProvider extends StateNotifier { }); } - Future addState( - {required Map data, - required String slug, - required String projectId}) async { + Future createState({required Map data}) async { + final projectId = + ref.read(ProviderList.projectProvider).currentProject['id']; + final slug = ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug; state = state.copyWith(createStateLoading: StateEnum.loading); final newState = await statesService.createState( data: data, slug: slug, projectId: projectId); @@ -101,7 +104,7 @@ class StatesProvider extends StateNotifier { final newStateGroupData = state.stateGroups; projectStates.addEntries({addedState.id: addedState}.entries); newStateGroupData.update( - addedState.group!, + addedState.group, (existingStates) => [...existingStates, addedState], ifAbsent: () => [addedState], ); @@ -130,7 +133,7 @@ class StatesProvider extends StateNotifier { final Map> updatedGroups = { ...state.stateGroups }; - final String groupId = updateState.group!; + final String groupId = updateState.group; final List? groupStates = updatedGroups[groupId]; if (groupStates != null) { final int indexToUpdate = @@ -164,19 +167,21 @@ class StatesProvider extends StateNotifier { delete.fold((deleted) { final projectStates = state.projectStates; projectStates.removeWhere((key, value) => key == stateId); - final Map> updatedGroups = { - ...state.stateGroups - }; - updatedGroups.forEach((groupId, groupStates) { - final int indexToRemove = - groupStates.indexWhere((s) => s.id == stateId); - if (indexToRemove != -1) { - groupStates.removeAt(indexToRemove); - updatedGroups[groupId] = groupStates; - } - }); - state = - state.copyWith(states: projectStates, stateGroups: updatedGroups, deleteState: StateEnum.success); + final Map> updatedGroups = { + ...state.stateGroups + }; + updatedGroups.forEach((groupId, groupStates) { + final int indexToRemove = + groupStates.indexWhere((s) => s.id == stateId); + if (indexToRemove != -1) { + groupStates.removeAt(indexToRemove); + updatedGroups[groupId] = groupStates; + } + }); + state = state.copyWith( + states: projectStates, + stateGroups: updatedGroups, + deleteState: StateEnum.success); }, (err) { state = state.copyWith(deleteState: StateEnum.error); log(err.response.toString()); diff --git a/lib/provider/views_provider.dart b/lib/provider/views_provider.dart index 5271dd6e..ff804321 100644 --- a/lib/provider/views_provider.dart +++ b/lib/provider/views_provider.dart @@ -63,8 +63,9 @@ class ViewsNotifier extends StateNotifier { {required dynamic data, required WidgetRef ref, required BuildContext context}) async { - final workspaceProvider = ref.watch(ProviderList.workspaceProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); + final workspaceProvider = ref.read(ProviderList.workspaceProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + final profileProvider = ref.read(ProviderList.profileProvider); try { final response = await DioConfig().dioServe( hasAuth: true, @@ -97,7 +98,8 @@ class ViewsNotifier extends StateNotifier { 'PROJECT_NAME': projectProvider.projectDetailModel!.name, 'VIEW_ID': response.data['id'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); } on DioException catch (e) { log(e.error.toString()); state = state.copyWith(viewsState: StateEnum.error); diff --git a/lib/provider/workspace_provider.dart b/lib/provider/workspace_provider.dart index 91e987a3..fa2c177f 100644 --- a/lib/provider/workspace_provider.dart +++ b/lib/provider/workspace_provider.dart @@ -6,7 +6,7 @@ import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/config/const.dart'; -import 'package:plane/models/workspace_model.dart'; +import 'package:plane/models/Workspace/workspace_model.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; @@ -163,7 +163,8 @@ class WorkspaceProvider extends ChangeNotifier { 'WORKSPACE_NAME': response.data['name'], 'WORKSPACE_SLUG': response.data['slug'] }, - ref: refs); + userEmail: profileProv.userProfile.email!, + userID: profileProv.userProfile.id!); await profileProv.updateProfile(data: { "last_workspace_id": response.data['id'], }); @@ -480,6 +481,7 @@ class WorkspaceProvider extends ChangeNotifier { } Future updateWorkspace({required Map data, required WidgetRef ref}) async { + final profileProvider = ref.read(ProviderList.profileProvider); updateWorkspaceState = StateEnum.loading; notifyListeners(); try { @@ -501,7 +503,8 @@ class WorkspaceProvider extends ChangeNotifier { 'WORKSPACE_NAME': response.data['name'], 'WORKSPACE_SLUG': response.data['slug'] }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); selectedWorkspace = WorkspaceModel.fromJson(response.data); tempLogo = selectedWorkspace.workspaceLogo; diff --git a/lib/repository/labels.service.dart b/lib/repository/labels.service.dart new file mode 100644 index 00000000..c0336d7d --- /dev/null +++ b/lib/repository/labels.service.dart @@ -0,0 +1,108 @@ +import 'dart:developer'; +import 'package:dartz/dartz.dart'; +import 'package:dio/dio.dart'; +import 'package:plane/config/apis.dart'; +import 'package:plane/models/Project/Label/label.model.dart'; +import 'package:plane/services/dio_service.dart'; +import 'package:plane/utils/enums.dart'; + +class LabelsService { + final DioConfig dio = DioConfig(); + + // GET Project Labels + Future, DioException>> getProjectLabels( + String slug, String projectID) async { + try { + final response = await dio.dioServe( + hasAuth: true, + url: + '${APIs.baseApi}/api/workspaces/$slug/projects/$projectID/issue-labels/', + hasBody: false, + httpMethod: HttpMethod.get, + ); + return Left({ + for (final label in response.data!) + label['id']: LabelModel.fromJson(label) + }); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } + + // GET Workspace Labels + Future, DioException>> getWorkspaceLabels( + String slug, String projectID) async { + try { + final response = await dio.dioServe( + hasAuth: true, + url: '${APIs.baseApi}/api/workspaces/labels/', + hasBody: false, + httpMethod: HttpMethod.get, + ); + return Left({ + for (final label in response.data!) + label['id']: LabelModel.fromJson(label) + }); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } + + // CREATE Label + Future> createLabel( + String slug, String projectID, Map payload) async { + try { + final response = await dio.dioServe( + hasAuth: true, + url: + '${APIs.baseApi}/api/workspaces/$slug/projects/$projectID/issue-labels/', + hasBody: true, + data: payload, + httpMethod: HttpMethod.post, + ); + return Left(LabelModel.fromJson(response.data)); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } + + // UPDATE Label + Future> updateLabel( + String slug, String projectID, Map payload) async { + try { + final response = await dio.dioServe( + hasAuth: true, + url: + '${APIs.baseApi}/api/workspaces/$slug/projects/$projectID/issue-labels/${payload['id']}/', + hasBody: true, + data: payload, + httpMethod: HttpMethod.post, + ); + return Left(LabelModel.fromJson(response.data)); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } + + // DELETE Label + Future> deleteLabel( + String slug, String projectID, String labelID) async { + try { + await dio.dioServe( + hasAuth: true, + url: + '${APIs.baseApi}/api/workspaces/$slug/projects/$projectID/issue-labels/$labelID/', + hasBody: false, + httpMethod: HttpMethod.delete, + ); + return const Left(null); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } +} diff --git a/lib/repository/states_service.dart b/lib/repository/states_service.dart index 4a146533..588dce3d 100644 --- a/lib/repository/states_service.dart +++ b/lib/repository/states_service.dart @@ -5,7 +5,7 @@ import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:plane/config/apis.dart'; -import 'package:plane/models/states_model.dart'; +import 'package:plane/models/Project/State/states_model.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/enums.dart'; diff --git a/lib/screens/MainScreens/Home/Dashboard/dash_board_screen.dart b/lib/screens/MainScreens/Home/Dashboard/dash_board_screen.dart index fd521dad..9a2ac91e 100644 --- a/lib/screens/MainScreens/Home/Dashboard/dash_board_screen.dart +++ b/lib/screens/MainScreens/Home/Dashboard/dash_board_screen.dart @@ -109,8 +109,8 @@ class _DashBoardScreenState extends ConsumerState { context, profileProvider, themeProvider), const SizedBox(height: 20), dashboardProvider.hideGithubBlock == false - ? starUsOnGitHubWidget( - themeProvider, context, dashboardProvider) + ? starUsOnGitHubWidget(themeProvider, context, + dashboardProvider, profileProvider) : Container(), const SizedBox(height: 20), projectProvider.projects.isEmpty && @@ -242,7 +242,7 @@ class _DashBoardScreenState extends ConsumerState { } Stack starUsOnGitHubWidget(ThemeProvider themeProvider, BuildContext context, - DashBoardProvider dashboardProvider) { + DashBoardProvider dashboardProvider, ProfileProvider profileProvider) { return Stack( children: [ Container( @@ -304,7 +304,8 @@ class _DashBoardScreenState extends ConsumerState { postHogService( eventName: 'STAR_US_ON_GITHIB', properties: {}, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( diff --git a/lib/screens/MainScreens/Profile/WorkpsaceSettings/invite_members.dart b/lib/screens/MainScreens/Profile/WorkpsaceSettings/invite_members.dart index a0f93e8e..2383f9c2 100644 --- a/lib/screens/MainScreens/Profile/WorkpsaceSettings/invite_members.dart +++ b/lib/screens/MainScreens/Profile/WorkpsaceSettings/invite_members.dart @@ -43,6 +43,7 @@ class _InviteMembersState extends ConsumerState { final themeProvider = ref.watch(ProviderList.themeProvider); final workspaceProvider = ref.watch(ProviderList.workspaceProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final profileProvider = ref.watch(ProviderList.profileProvider); final BuildContext mainBuildContext = context; return GestureDetector( onTap: () { @@ -459,7 +460,9 @@ class _InviteMembersState extends ConsumerState { properties: { 'INVITED_USER_EMAIL': emailController.text, }, - ref: ref); + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); + if (workspaceProvider.workspaceInvitationState == StateEnum.success) { CustomToast.showToast(mainBuildContext, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart index 22472a66..5a9b6f1c 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart @@ -56,7 +56,6 @@ class _CreateIssueState extends ConsumerState Map tempStates = {}; List tempStateOrdering = []; Map tempStatesIcons = {}; - List tempLabels = []; List tempIssues = []; List tempAssignees = []; bool descriptionExpanded = false; @@ -67,7 +66,9 @@ class _CreateIssueState extends ConsumerState void initCreateIssue() { final prov = ref.read(ProviderList.issuesProvider); final projectProvider = ref.read(ProviderList.projectProvider); - final statesProvider = ref.read(ProviderList.statesProvider.notifier); + final statesNotifier = ref.read(ProviderList.statesProvider.notifier); + final statesProvider = ref.read(ProviderList.statesProvider); + ref.read(ProviderList.issueProvider).initCookies(); prov.createIssueProjectData = widget.projectId != null ? projectProvider.projects @@ -75,16 +76,14 @@ class _CreateIssueState extends ConsumerState : projectProvider.currentProject; final themeProvider = ref.read(ProviderList.themeProvider); tempStatesData = prov.statesData; - tempStates = prov.states; - tempStateOrdering = prov.stateOrdering; + tempStates = statesProvider.projectStates; tempStatesIcons = prov.stateIcons; - tempLabels = prov.labels; tempIssues = ref.read(ProviderList.searchIssueProvider).issues; tempAssignees = projectProvider.projectMembers; if (widget.fromMyIssues) { - prov.statesState = StateEnum.loading; - statesProvider + statesProvider.statesState = StateEnum.loading; + statesNotifier .getStates( slug: ref .read(ProviderList.workspaceProvider) @@ -93,8 +92,9 @@ class _CreateIssueState extends ConsumerState projectId: widget.projectId ?? ref.read(ProviderList.projectProvider).currentProject['id']) .then((value) { - prov.createIssuedata['state'] = - (prov.states.isNotEmpty ? prov.states.keys.first : null); + prov.createIssuedata['state'] = (statesProvider.projectStates.isNotEmpty + ? statesProvider.projectStates.keys.first + : null); }); ref.read(ProviderList.estimatesProvider).getEstimates( @@ -106,14 +106,14 @@ class _CreateIssueState extends ConsumerState ref.read(ProviderList.projectProvider).currentProject['id']); } else { bool found = false; - for (final element in prov.states.keys) { + for (final element in statesProvider.projectStates.keys) { if (element == prov.createIssuedata['state']) { found = true; } } if (!found) { - prov.createIssuedata['state'] = prov.states.keys.first; + prov.createIssuedata['state'] = statesProvider.projectStates.keys.first; } } @@ -141,7 +141,7 @@ class _CreateIssueState extends ConsumerState LoadingType getLoading(WidgetRef ref) { return setWidgetState([ ref.read(ProviderList.issuesProvider).createIssueState, - ref.read(ProviderList.issuesProvider).statesState, + ref.read(ProviderList.statesProvider).statesState, ], loadingType: LoadingType.wrap); } @@ -165,22 +165,21 @@ class _CreateIssueState extends ConsumerState final themeProvider = ref.watch(ProviderList.themeProvider); final issuesProvider = ref.watch(ProviderList.issuesProvider); final projectProvider = ref.watch(ProviderList.projectProvider); - final statesProvider = ref.watch(ProviderList.statesProvider.notifier); + final statesNotifier = ref.watch(ProviderList.statesProvider.notifier); final estimatesProvider = ref.watch(ProviderList.estimatesProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); final BuildContext baseContext = context; if (issuesProvider.createIssuedata['state'] == null && - issuesProvider.states.isNotEmpty) { + statesProvider.projectStates.isNotEmpty) { issuesProvider.createIssuedata['state'] = - issuesProvider.states.keys.first; + statesProvider.projectStates.keys.first; } return WillPopScope( onWillPop: () async { issuesProvider.createIssuedata = {}; issuesProvider.statesData = tempStatesData; // issuesProvider.states = tempStates; - issuesProvider.stateOrdering = tempStateOrdering; issuesProvider.stateIcons = tempStatesIcons; - issuesProvider.labels = tempLabels; projectProvider.projectMembers = tempAssignees; issuesProvider.setsState(); ref.read(ProviderList.searchIssueProvider).issues = tempIssues; @@ -197,9 +196,7 @@ class _CreateIssueState extends ConsumerState issuesProvider.createIssuedata = {}; issuesProvider.statesData = tempStatesData; // issuesProvider.states = tempStates; - issuesProvider.stateOrdering = tempStateOrdering; issuesProvider.stateIcons = tempStatesIcons; - issuesProvider.labels = tempLabels; projectProvider.projectMembers = tempAssignees; issuesProvider.setsState(); ref.read(ProviderList.issueProvider).clearCookies(); @@ -271,7 +268,7 @@ class _CreateIssueState extends ConsumerState builder: (ctx) => const SelectProject()).then( (value) { - statesProvider + statesNotifier .getStates( slug: ref .read(ProviderList @@ -284,7 +281,8 @@ class _CreateIssueState extends ConsumerState .then((value) { issuesProvider .createIssuedata['state'] = - issuesProvider.states.keys.first; + statesProvider + .projectStates.keys.first; }); ref .read( @@ -788,7 +786,7 @@ class _CreateIssueState extends ConsumerState // .themeManager // .primaryTextColor, // ), - + issuesProvider.createIssuedata[ 'state'] == null @@ -1838,9 +1836,7 @@ class _CreateIssueState extends ConsumerState issuesProvider.createIssuedata = {}; issuesProvider.statesData = tempStatesData; // issuesProvider.states = tempStates; - issuesProvider.stateOrdering = tempStateOrdering; issuesProvider.stateIcons = tempStatesIcons; - issuesProvider.labels = tempLabels; projectProvider.projectMembers = tempAssignees; issuesProvider.setsState(); ref.read(ProviderList.searchIssueProvider).issues = @@ -1871,17 +1867,15 @@ class _CreateIssueState extends ConsumerState final themeProvider = ref.read(ProviderList.themeProvider); tempStatesData = issuesProvider.statesData; - tempStates = issuesProvider.states; - tempStateOrdering = issuesProvider.stateOrdering; + tempStates = statesProvider.projectStates; tempStatesIcons = issuesProvider.stateIcons; - tempLabels = issuesProvider.labels; tempIssues = ref .read(ProviderList.searchIssueProvider) .issues; tempAssignees = projectProvider.projectMembers; if (widget.fromMyIssues) { - statesProvider + statesNotifier .getStates( slug: ref .read( @@ -1895,8 +1889,9 @@ class _CreateIssueState extends ConsumerState .currentProject['id']) .then((value) { issuesProvider.createIssuedata['state'] = - (issuesProvider.states.isNotEmpty - ? issuesProvider.states.keys.first + (statesProvider.projectStates.isNotEmpty + ? statesProvider + .projectStates.keys.first : null); }); diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart index e40857f3..6a6af532 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart @@ -16,10 +16,11 @@ class _IssuesTabState extends ConsumerState { @override Widget build(BuildContext context) { final issueProvider = ref.watch(ProviderList.issuesProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); return LoadingWidget( loading: issueProvider.issuePropertyState == StateEnum.loading || issueProvider.issueState == StateEnum.loading || - issueProvider.statesState == StateEnum.loading || + statesProvider.statesState == StateEnum.loading || issueProvider.projectViewState == StateEnum.loading || issueProvider.orderByState == StateEnum.loading, widgetClass: IssueLayoutHandler( diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_detail.dart index 476feb88..f2f37ac5 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_detail.dart @@ -56,12 +56,7 @@ class _PageDetailState extends ConsumerState { .workspaceSlug, projectId: ref.read(ProviderList.projectProvider).currentProject["id"], ref: ref); - ref.read(ProviderList.issuesProvider).getLabels( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: ref.read(ProviderList.projectProvider).currentProject["id"]); + ref.read(ProviderList.labelProvider.notifier).getProjectLabels(); for (final element in (prov.pages[prov.selectedFilter]![widget.index] ['label_details'] as List)) { prov.selectedLabels.add(element['id']); diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart index 40fcb6d4..967856b4 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart @@ -1,5 +1,4 @@ import 'dart:math'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/utils/custom_toast.dart'; @@ -45,7 +44,7 @@ class _CreateLabelState extends ConsumerState { @override Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); - final issuesProvider = ref.read(ProviderList.issuesProvider); + final labelNotifier = ref.read(ProviderList.labelProvider.notifier); return GestureDetector( onTap: () { setState(() { @@ -210,21 +209,11 @@ class _CreateLabelState extends ConsumerState { message: "Color is not valid", toastType: ToastType.failure); } else { - issuesProvider.issueLabels( - slug: ref - .watch(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: ref - .watch(ProviderList.projectProvider) - .currentProject['id'], - method: widget.method, - data: { - "name": lableController.text, - "color": '#${colorController.text}', - }, - labelId: widget.labelId, - ref: ref); + + labelNotifier.createLabel({ + "name": lableController.text, + "color": '#${colorController.text}', + }); Navigator.of(context).pop(); } }, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/features_page.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/features_page.dart index 508c3e4a..8b487d51 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/features_page.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/features_page.dart @@ -54,6 +54,7 @@ class _FeaturesPageState extends ConsumerState { Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); final projectsProvider = ref.watch(ProviderList.projectProvider); + final profileProvider = ref.watch(ProviderList.profileProvider); return Container( color: themeProvider.themeManager.primaryBackgroundDefaultColor, child: ListView.builder( @@ -152,10 +153,10 @@ class _FeaturesPageState extends ConsumerState { : 'OFF'; postHogService( - eventName: prefix + suffix, - properties: {}, - ref: ref, - ); + eventName: prefix + suffix, + properties: {}, + userEmail: profileProvider.userProfile.email!, + userID: profileProvider.userProfile.id!); } : () { CustomToast.showToast(context, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/lables_page.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/lables_page.dart index e2a99fff..d91f7009 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/lables_page.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/lables_page.dart @@ -22,9 +22,9 @@ class LablesPage extends ConsumerStatefulWidget { class _LablesPageState extends ConsumerState { List expanded = []; bool isChildAvailable(String id) { - final issuesProv = ref.read(ProviderList.issuesProvider); - for (final element in issuesProv.labels) { - if (element["parent"] == id) return true; + final labelProvider = ref.read(ProviderList.labelProvider); + for (final label in labelProvider.projectLabels.values) { + if (label.parent == id) return true; } return false; } @@ -32,21 +32,24 @@ class _LablesPageState extends ConsumerState { @override Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); - final issuesProvider = ref.watch(ProviderList.issuesProvider); + final labelProvider = ref.watch(ProviderList.labelProvider); + final labelNotifier = ref.read(ProviderList.labelProvider.notifier); + return LoadingWidget( - loading: issuesProvider.labelState == StateEnum.loading, + loading: labelProvider.labelState == StateEnum.loading, widgetClass: Container( color: themeProvider.themeManager.primaryBackgroundDefaultColor, - child: issuesProvider.labels.isEmpty + child: labelProvider.projectLabels.isEmpty ? EmptyPlaceholder.emptyLabels(context, ref) : ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), - itemCount: issuesProvider.labels.length, + itemCount: labelProvider.projectLabels.length, itemBuilder: (context, index) { - final isChildAvail = - isChildAvailable(issuesProvider.labels[index]["id"]); - return issuesProvider.labels[index]["parent"] == null + final label = + labelProvider.projectLabels.values.elementAt(index); + final isChildAvail = isChildAvailable(label.id); + return label.parent == null ? Container( margin: const EdgeInsets.only(bottom: 10), decoration: BoxDecoration( @@ -71,18 +74,13 @@ class _LablesPageState extends ConsumerState { !isChildAvail ? CircleAvatar( radius: 6, - backgroundColor: issuesProvider - .labels[index]['color'] - .toString() - .toColor(), + backgroundColor: + label.color.toColor(), ) : SvgPicture.asset( "assets/svg_images/label_group.svg", colorFilter: ColorFilter.mode( - issuesProvider.labels[index] - ['color'] - .toString() - .toColor(), + label.color.toColor(), BlendMode.srcIn), ), const SizedBox( @@ -94,8 +92,7 @@ class _LablesPageState extends ConsumerState { .width * 0.7, child: CustomText( - issuesProvider.labels[index] - ['name'], + label.name, type: FontStyle.H5, maxLines: 1, color: themeProvider @@ -145,14 +142,9 @@ class _LablesPageState extends ConsumerState { .viewInsets .bottom), child: CreateLabel( - label: issuesProvider - .labels[index] - ['name'], - labelColor: issuesProvider - .labels[index] - ['color'], - labelId: issuesProvider - .labels[index]['id'], + label: label.name, + labelColor: label.color, + labelId: label.id, method: CRUD.update, ), ); @@ -182,8 +174,7 @@ class _LablesPageState extends ConsumerState { context: context, builder: (context) { return SingleLabelSelect( - labelID: issuesProvider - .labels[index]["id"], + labelID: label.id, ); }, ); @@ -212,11 +203,8 @@ class _LablesPageState extends ConsumerState { .viewInsets .bottom), child: DeleteLabelSheet( - labelName: issuesProvider - .labels[index] - ['name'], - labelId: issuesProvider - .labels[index]['id'], + labelName: label.name, + labelId: label.id, ), ); }, @@ -347,11 +335,9 @@ class _LablesPageState extends ConsumerState { ), Column( children: expanded.contains(index) - ? issuesProvider.labels.map( - (e) { - return e["parent"] == - issuesProvider.labels[index] - ["id"] + ? labelProvider.projectLabels.values.map( + (childLabel) { + return childLabel.parent == label.id ? Container( margin: const EdgeInsets.only( @@ -383,16 +369,16 @@ class _LablesPageState extends ConsumerState { children: [ CircleAvatar( radius: 6, - backgroundColor: e[ - 'color'] - .toString() - .toColor(), + backgroundColor: + childLabel + .color + .toColor(), ), const SizedBox( width: 10, ), CustomText( - e['name'], + childLabel.name, type: FontStyle .Medium, maxLines: 3, @@ -448,12 +434,14 @@ class _LablesPageState extends ConsumerState { .bottom), child: CreateLabel( - label: e[ - 'name'], + label: childLabel + .name, labelColor: - e['color'], - labelId: e[ - 'id'], + childLabel + .color, + labelId: + childLabel + .id, method: CRUD .update, ), @@ -462,27 +450,10 @@ class _LablesPageState extends ConsumerState { ); } else if (val == 'CONVERT') { - issuesProvider - .issueLabels( - slug: ref - .watch(ProviderList - .workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: ref - .watch(ProviderList - .projectProvider) - .currentProject[ - 'id'], - method: CRUD - .update, - data: { - "parent": - null, - }, - labelId: e[ - "id"], - ref: ref); + labelNotifier + .updateLabel({ + "parent": null, + }); } else { showModalBottomSheet( constraints: @@ -516,9 +487,11 @@ class _LablesPageState extends ConsumerState { child: DeleteLabelSheet( labelName: - e['name'], - labelId: e[ - 'id'], + childLabel + .name, + labelId: + childLabel + .id, ), ); }, @@ -627,34 +600,36 @@ class SingleLabelSelect extends ConsumerStatefulWidget { class _SingleLabelSelectState extends ConsumerState { double height = 0.0; bool isChildAvailable(String id) { - final issuesProv = ref.read(ProviderList.issuesProvider); - for (final element in issuesProv.labels) { - if (element["parent"] == id) return true; + final labelProv = ref.read(ProviderList.labelProvider); + for (final label in labelProv.projectLabels.values) { + if (label.parent == id) return true; } return false; } bool isLabelsAvailable({int index = 0, bool iterate = false}) { - final issuesProvider = ref.read(ProviderList.issuesProvider); + final labelProv = ref.read(ProviderList.labelProvider); if (iterate) { - for (final element in issuesProvider.labels) { - if (!(element["id"] == widget.labelID || - element["parent"] == widget.labelID || - element["parent"] != null || - isChildAvailable(element["id"]))) return false; + for (final label in labelProv.projectLabels.values) { + if (!(label.id == widget.labelID || + label.parent == widget.labelID || + label.parent != null || + isChildAvailable(label.id))) return false; } return true; } - return issuesProvider.labels[index]["id"] == widget.labelID || - issuesProvider.labels[index]["parent"] == widget.labelID || - issuesProvider.labels[index]["parent"] != null || - isChildAvailable(issuesProvider.labels[index]["id"]); + final label = labelProv.projectLabels.values.elementAt(index); + return label.id == widget.labelID || + label.parent == widget.labelID || + label.parent != null || + isChildAvailable(label.id); } @override Widget build(BuildContext context) { - final issuesProvider = ref.watch(ProviderList.issuesProvider); final themeProvider = ref.watch(ProviderList.themeProvider); + final labelProvider = ref.read(ProviderList.labelProvider); + final labelNotifier = ref.read(ProviderList.labelProvider.notifier); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { final box = context.findRenderObject() as RenderBox; height = box.size.height; @@ -695,29 +670,20 @@ class _SingleLabelSelectState extends ConsumerState { isLabelsAvailable(iterate: true) ? EmptyPlaceholder.emptyLabels(context, ref) : ListView.builder( - itemCount: issuesProvider.labels.length, + itemCount: labelProvider.projectLabels.length, shrinkWrap: true, itemBuilder: (context, index) { + final label = + labelProvider.projectLabels.values.elementAt( + index, + ); return isLabelsAvailable(index: index) ? Container() : InkWell( onTap: () { - issuesProvider.issueLabels( - slug: ref - .watch( - ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: ref - .watch(ProviderList.projectProvider) - .currentProject['id'], - method: CRUD.update, - data: { - "parent": widget.labelID, - }, - labelId: issuesProvider.labels[index] - ["id"], - ref: ref); + labelNotifier.updateLabel({ + "parent": null, + }); Navigator.pop(context); }, @@ -731,16 +697,12 @@ class _SingleLabelSelectState extends ConsumerState { children: [ CircleAvatar( radius: 8, - backgroundColor: issuesProvider - .labels[index]['color'] - .toString() - .toColor(), + backgroundColor: + label.color.toColor(), ), Container(width: 10), CustomText( - issuesProvider.labels[index] - ['name'] - .toString(), + label.name, type: FontStyle.Small, ), const Spacer(), @@ -761,7 +723,7 @@ class _SingleLabelSelectState extends ConsumerState { ], ), ), - issuesProvider.labelState == StateEnum.loading + labelProvider.labelState == StateEnum.loading ? Container( height: height - 32, alignment: Alignment.center, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart index 42326926..6813323e 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart @@ -7,9 +7,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/bottom_sheets/delete_state_sheet.dart'; -import 'package:plane/provider/issues_provider.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/provider/states_provider.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; @@ -223,7 +221,7 @@ class _StatesPageState extends ConsumerState { onPressed: () { if (statesProvider.stateGroups.values .toList()[index][idx] - .isDefault == + .is_default == true) { CustomToast.showToast( context, @@ -296,7 +294,7 @@ class _StatesPageState extends ConsumerState { Color getColorFromIssueProvider(int index, int idx) { final statesProvider = ref.watch(ProviderList.statesProvider); const Color colorToReturnOnApiError = Color.fromARGB(255, 200, 80, 80); - final String? colorData = + final String colorData = statesProvider.stateGroups.values.toList()[index][idx].color; return (colorData == null || colorData[0] != '#') ? colorToReturnOnApiError @@ -728,20 +726,14 @@ class _AddUpdateStateState extends ConsumerState { ontap: () async { if (nameController.text.isNotEmpty) { if (widget.method == CRUD.create) { - statesProviderRead.addState( - data: { - "name": nameController.text, - "color": '#${colorController.text}', - "group": stateController.text.toLowerCase(), - "description": "" - }, - slug: ref - .watch(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: ref - .watch(ProviderList.projectProvider) - .currentProject['id']); + statesProviderRead.createState( + data: { + "name": nameController.text, + "color": '#${colorController.text}', + "group": stateController.text.toLowerCase(), + "description": "" + }, + ); } else { statesProviderRead.updateState( data: { diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart index ce26f33d..b948a593 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart @@ -97,10 +97,7 @@ class _ViewsDetailState extends ConsumerState { final issuesProvider = ref.watch(ProviderList.issuesProvider); final viewsProv = ref.watch(ProviderList.viewsProvider); final themeProvider = ref.watch(ProviderList.themeProvider); - - // viewData = viewsProv.viewDetail; - - log(issuesProvider.issues.filters.priorities.toString()); + final statesProvider = ref.watch(ProviderList.statesProvider); return WillPopScope( onWillPop: () async { if (!widget.fromGlobalSearch) { @@ -176,7 +173,7 @@ class _ViewsDetailState extends ConsumerState { body: LoadingWidget( loading: issuesProvider.issuePropertyState == StateEnum.loading || issuesProvider.issueState == StateEnum.loading || - issuesProvider.statesState == StateEnum.loading || + statesProvider.statesState == StateEnum.loading || issuesProvider.projectViewState == StateEnum.loading || issuesProvider.orderByState == StateEnum.loading || viewsProv.viewsState == StateEnum.loading, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart b/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart index ca14e26c..5b8bc76a 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart @@ -43,7 +43,7 @@ class _ArchivedIssuesState extends ConsumerState { final themeProvider = ref.watch(ProviderList.themeProvider); final issueProvider = ref.watch(ProviderList.issuesProvider); final projectProvider = ref.watch(ProviderList.projectProvider); - // log(issueProvider.issueState.name); + final statesProvider = ref.watch(ProviderList.statesProvider); if (issueProvider.issues.projectView == IssueLayout.list) { issueProvider.initializeBoard( isArchive: true, @@ -86,10 +86,10 @@ class _ArchivedIssuesState extends ConsumerState { body: LoadingWidget( loading: issueProvider.issuePropertyState == StateEnum.loading || issueProvider.issueState == StateEnum.loading || - issueProvider.statesState == StateEnum.loading || + statesProvider.statesState == StateEnum.loading || issueProvider.projectViewState == StateEnum.loading || issueProvider.orderByState == StateEnum.loading, - widgetClass: issueProvider.statesState == StateEnum.restricted + widgetClass: statesProvider.statesState == StateEnum.restricted ? EmptyPlaceholder.joinProject( context, ref, @@ -102,7 +102,7 @@ class _ArchivedIssuesState extends ConsumerState { color: themeProvider .themeManager.secondaryBackgroundDefaultColor, child: issueProvider.issueState == StateEnum.loading || - issueProvider.statesState == StateEnum.loading || + statesProvider.statesState == StateEnum.loading || issueProvider.projectViewState == StateEnum.loading || issueProvider.orderByState == StateEnum.loading ? Container() @@ -291,7 +291,7 @@ class _ArchivedIssuesState extends ConsumerState { ), ), ), - issueProvider.statesState == + statesProvider.statesState == StateEnum.loading || issueProvider.issueState == StateEnum.loading diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart index 379ce7df..e1d99a2c 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart @@ -46,11 +46,12 @@ class _ProjectDetailState extends ConsumerState { @override void initState() { final issueProvider = ref.read(ProviderList.issuesProvider); + final statesProvider = ref.read(ProviderList.statesProvider); issueProvider.orderByState = StateEnum.loading; - issueProvider.statesState = StateEnum.restricted; + statesProvider.statesState = StateEnum.restricted; WidgetsBinding.instance.addPostFrameCallback((timeStamp) { issueProvider.setsState(); - issueProvider.statesState = StateEnum.restricted; + statesProvider.statesState = StateEnum.restricted; ref.read(ProviderList.projectProvider).initializeProject(ref: ref); }); @@ -59,8 +60,8 @@ class _ProjectDetailState extends ConsumerState { @override Widget build(BuildContext context) { - final issueProvider = ref.watch(ProviderList.issuesProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); return Scaffold( appBar: ProjectDetailAppbar( @@ -71,7 +72,7 @@ class _ProjectDetailState extends ConsumerState { floatingActionButton: FLActionButton(context, ref: ref, selected: selectedTab), body: SafeArea( - child: issueProvider.statesState == StateEnum.restricted + child: statesProvider.statesState == StateEnum.restricted ? EmptyPlaceholder.joinProject( context, ref, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart index d7abdec0..8bac38b7 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart @@ -14,8 +14,7 @@ PreferredSizeWidget ProjectDetailAppbar( }) { final themeProvider = ref.read(ProviderList.themeProvider); final projectProvider = ref.read(ProviderList.projectProvider); - final issueProvider = ref.read(ProviderList.issuesProvider); - + final statesProvider = ref.watch(ProviderList.statesProvider); return CustomAppBar( elevation: false, onPressed: () { @@ -26,7 +25,7 @@ PreferredSizeWidget ProjectDetailAppbar( (projectProvider.currentProject['archive_in'] > 0 && (projectProvider.role == Role.admin || projectProvider.role == Role.member) && - (issueProvider.statesState == StateEnum.success)) + (statesProvider.statesState == StateEnum.success)) ? IconButton( onPressed: () { Navigator.of(context).push( @@ -40,7 +39,7 @@ PreferredSizeWidget ProjectDetailAppbar( color: themeProvider.themeManager.placeholderTextColor, )) : Container(), - (issueProvider.statesState == StateEnum.success) + (statesProvider.statesState == StateEnum.success) ? IconButton( onPressed: () { Navigator.push( @@ -52,7 +51,7 @@ PreferredSizeWidget ProjectDetailAppbar( settingsOntap(); }); }, - icon: issueProvider.statesState == StateEnum.restricted + icon: statesProvider.statesState == StateEnum.restricted ? Container() : Icon( Icons.settings_outlined, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart index 73d20140..d37eb90a 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart @@ -26,17 +26,18 @@ class _PDBottomActionsState extends ConsumerState { final projectProvider = ref.watch(ProviderList.projectProvider); final issueProvider = ref.watch(ProviderList.issuesProvider); final pageProvider = ref.watch(ProviderList.pageProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); return Row( children: [ - issueProvider.statesState == StateEnum.loading || + statesProvider.statesState == StateEnum.loading || issueProvider.issueState == StateEnum.loading ? Container() : widget.selectedTab == 0 && - issueProvider.statesState == StateEnum.restricted + statesProvider.statesState == StateEnum.restricted ? Container() : widget.selectedTab == 0 && - issueProvider.statesState == StateEnum.success + statesProvider.statesState == StateEnum.success ? Container( decoration: BoxDecoration( color: themeProvider @@ -54,7 +55,7 @@ class _PDBottomActionsState extends ConsumerState { child: InkWell( onTap: () { issueProvider.createIssuedata['state'] = - issueProvider.states.keys.first; + statesProvider.projectStates.keys.first; Navigator.of(context).push( MaterialPageRoute( diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart index d43fa631..c73802ec 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart @@ -50,8 +50,8 @@ class _ProjectDetailRootState extends ConsumerState { @override Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); - final issueProvider = ref.watch(ProviderList.issuesProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); return projectProvider.projectDetailState == StateEnum.error ? errorState( @@ -63,7 +63,7 @@ class _ProjectDetailRootState extends ConsumerState { }) : Column( children: [ - issueProvider.statesState != StateEnum.loading + statesProvider.statesState != StateEnum.loading ? ProjectDetailTabs( selectedTab: widget.selectedTab, onTabChange: widget.onTabChange, diff --git a/lib/screens/create_state.dart b/lib/screens/create_state.dart index 2163c3f4..6d755bbd 100644 --- a/lib/screens/create_state.dart +++ b/lib/screens/create_state.dart @@ -47,7 +47,8 @@ class _CreateStateState extends ConsumerState { @override Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); - final issuesProvider = ref.watch(ProviderList.issuesProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); + final statesNotifier = ref.read(ProviderList.statesProvider.notifier); return Scaffold( appBar: CustomAppBar( onPressed: () { @@ -56,7 +57,7 @@ class _CreateStateState extends ConsumerState { text: 'Create State', ), body: LoadingWidget( - loading: issuesProvider.statesState == StateEnum.loading, + loading: statesProvider.statesState == StateEnum.loading, widgetClass: SingleChildScrollView( child: Form( key: formKey, @@ -400,14 +401,7 @@ class _CreateStateState extends ConsumerState { text: 'Create State', ontap: () async { if (!formKey.currentState!.validate()) return; - await issuesProvider.createState( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: ref - .read(ProviderList.projectProvider) - .currentProject["id"], + await statesNotifier.createState( data: { "name": name.text, "color": "#${colorController.text}", diff --git a/lib/screens/create_view_screen.dart b/lib/screens/create_view_screen.dart index b136cb62..5fb1cc98 100644 --- a/lib/screens/create_view_screen.dart +++ b/lib/screens/create_view_screen.dart @@ -108,6 +108,8 @@ class _CreateViewState extends ConsumerState { final viewsProvider = ref.watch(ProviderList.viewsProvider); final issuesProvider = ref.watch(ProviderList.issuesProvider); final projectProvider = ref.watch(ProviderList.projectProvider); + final labelProvider = ref.watch(ProviderList.labelProvider); + final statesProvider = ref.watch(ProviderList.statesProvider); return GestureDetector( onTap: () { FocusScope.of(context).unfocus(); @@ -250,189 +252,215 @@ class _CreateViewState extends ConsumerState { itemCount: filtersData['Filters']!.length, primary: false, shrinkWrap: true, - itemBuilder: - ((context, index) => - filtersData['Filters']! - .values - .elementAt(index) - .isNotEmpty - ? Container( - padding: - const EdgeInsets.only( - top: 10, - bottom: 10, - left: 10, - right: 10), - margin: const EdgeInsets.only( - bottom: 10), - decoration: BoxDecoration( + itemBuilder: ((context, index) => + filtersData['Filters']! + .values + .elementAt(index) + .isNotEmpty + ? Container( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + left: 10, + right: 10), + margin: const EdgeInsets.only( + bottom: 10), + decoration: BoxDecoration( + color: themeProvider + .themeManager + .primaryBackgroundDefaultColor, + borderRadius: + BorderRadius.circular(4), + border: Border.all( color: themeProvider .themeManager - .primaryBackgroundDefaultColor, - borderRadius: - BorderRadius.circular( - 4), - border: Border.all( - color: themeProvider - .themeManager - .borderStrong01Color)), - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - CustomText( - filterKeys[index], - fontWeight: FontWeightt - .Semibold, - ), - const SizedBox( - height: 10, - ), - Wrap( - children: ((filtersData['Filters'] as Map).values.elementAt(index) as List) - .map((e) => filterKeys[index] == 'Priority:' - ? GestureDetector( - onTap: () { - log(e); - ((filtersData['Filters'] as Map).values.elementAt(index) - as List) - .remove( - e); - setState( - () {}); - }, - child: - filterWidget( - color: priorities[ - e] - [ - 'color'], - icon: - Icon( - priorities[e] - [ - 'icon'], - size: + .borderStrong01Color)), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + CustomText( + filterKeys[index], + fontWeight: + FontWeightt.Semibold, + ), + const SizedBox( + height: 10, + ), + Wrap( + children: + ((filtersData['Filters'] + as Map) + .values + .elementAt( + index) + as List) + .map((e) { + return filterKeys[ + index] == + 'Priority:' + ? GestureDetector( + onTap: () { + ((filtersData['Filters'] + as Map) + .values + .elementAt( + index) as List) + .remove(e); + setState(() {}); + }, + child: + filterWidget( + color: + priorities[ + e][ + 'color'], + icon: Icon( + priorities[e] + ['icon'], + size: 15, + color: priorities[ + e] + ['color'], + ), + text: + priorities[ + e][ + 'text'], + ), + ) + : filterKeys[index] == + 'State:' + ? GestureDetector( + onTap: () { + ((filtersData['Filters'] + as Map) + .values + .elementAt(index) as List) + .remove(e); + setState( + () {}); + }, + child: + filterWidget( + color: statesProvider + .projectStates[ + e]! + .color + .toColor(), + icon: SizedBox( + height: 15, - color: priorities[e] - [ - 'color'], - ), - text: priorities[ - e] - [ - 'text'], - ), - ) - : filterKeys[index] == 'State:' - ? GestureDetector( - onTap: - () { - ((filtersData['Filters'] as Map).values.elementAt(index) as List) - .remove(e); - setState( - () {}); - }, - child: - filterWidget( - color: issuesProvider - .states[e]!.color - .toString() - .toColor(), - icon: SizedBox( - height: 15, - width: 15, - child: issuesProvider.stateIcons[e]), - text: issuesProvider.states[e] - !.name!, - ), - ) - : filterKeys[index] == 'Assignees:' || filterKeys[index] == 'Created By:' - ? GestureDetector( - onTap: - () { - ((filtersData['Filters'] as Map).values.elementAt(index) as List).remove(e); - setState(() {}); - }, - child: - filterWidget( - fill: false, - color: Colors.black, - icon: projectProvider.projectMembers.where((element) => element['member']["id"] == e).first['member']['avatar'] != '' - ? CircleAvatar( - radius: 10, - backgroundImage: NetworkImage(projectProvider.projectMembers.where((element) => element['member']["id"] == e).first['member']['avatar']), - ) - : CircleAvatar( - radius: 10, - backgroundColor: const Color.fromRGBO(55, 65, 81, 1), - child: Center( - child: CustomText( - projectProvider.projectMembers.where((element) => element['member']["id"] == e).first['member']['first_name'][0].toString().toUpperCase(), - color: Colors.white, - fontSize: 12, - )), - ), - text: projectProvider.projectMembers.where((element) => element['member']["id"] == e).first['member']['display_name'] ?? '', - ), - ) - : filterKeys[index] == 'Labels:' - ? GestureDetector( - onTap: () { - ((filtersData['Filters'] as Map).values.elementAt(index) as List).remove(e); - setState(() {}); - }, - child: filterWidget( - color: issuesProvider.labels.where((element) => element["id"] == e).first['color'].toString().toUpperCase().toColor(), - icon: Container( - height: 15, - width: 15, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: issuesProvider.labels.where((element) => element["id"] == e).first['color'].toString().toUpperCase().toColor(), - ), - ), - text: issuesProvider.labels.where((element) => element["id"] == e).first["name"]), + width: + 15, + child: issuesProvider + .stateIcons[e]), + text: statesProvider + .projectStates[ + e]! + .name, + ), + ) + : filterKeys[index] == + 'Assignees:' || + filterKeys[ + index] == + 'Created By:' + ? GestureDetector( + onTap: + () { + ((filtersData['Filters'] as Map).values.elementAt(index) + as List) + .remove(e); + setState( + () {}); + }, + child: + filterWidget( + fill: + false, + color: Colors + .black, + icon: projectProvider.projectMembers.where((element) => element['member']["id"] == e).first['member']['avatar'] != + '' + ? CircleAvatar( + radius: 10, + backgroundImage: NetworkImage(projectProvider.projectMembers.where((element) => element['member']["id"] == e).first['member']['avatar']), ) - : filterKeys[index] == 'Target Date:' - ? GestureDetector( - onTap: () { - ((filtersData['Filters'] as Map).values.elementAt(index) as List).remove(e); - setState(() {}); - }, - child: filterWidget( - color: Colors.black, - icon: Icon( - Icons.calendar_today_outlined, - size: 15, - color: themeProvider.themeManager.placeholderTextColor, - ), - text: e, + : CircleAvatar( + radius: 10, + backgroundColor: const Color.fromRGBO(55, 65, 81, 1), + child: Center( + child: CustomText( + projectProvider.projectMembers.where((element) => element['member']["id"] == e).first['member']['first_name'][0].toString().toUpperCase(), + color: Colors.white, + fontSize: 12, + )), + ), + text: projectProvider.projectMembers.where((element) => element['member']["id"] == e).first['member']['display_name'] ?? + '', + ), + ) + : filterKeys[ + index] == + 'Labels:' + ? GestureDetector( + onTap: + () { + ((filtersData['Filters'] as Map).values.elementAt(index) as List).remove(e); + setState(() {}); + }, + child: filterWidget( + color: labelProvider.projectLabels[e]!.color.toUpperCase().toColor(), + icon: Container( + height: 15, + width: 15, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: labelProvider.projectLabels[e]!.color.toUpperCase().toColor(), + ), + ), + text: labelProvider.projectLabels[e]!.name), + ) + : filterKeys[index] == + 'Target Date:' + ? GestureDetector( + onTap: () { + ((filtersData['Filters'] as Map).values.elementAt(index) as List).remove(e); + setState(() {}); + }, + child: filterWidget( + color: Colors.black, + icon: Icon( + Icons.calendar_today_outlined, + size: 15, + color: themeProvider.themeManager.placeholderTextColor, + ), + text: e, + ), + ) + : filterKeys[index] == 'Start Date:' + ? GestureDetector( + onTap: () { + ((filtersData['Filters'] as Map).values.elementAt(index) as List).remove(e); + setState(() {}); + }, + child: filterWidget( + color: Colors.black, + icon: Icon( + Icons.calendar_today_outlined, + size: 15, + color: themeProvider.themeManager.placeholderTextColor, ), - ) - : filterKeys[index] == 'Start Date:' - ? GestureDetector( - onTap: () { - ((filtersData['Filters'] as Map).values.elementAt(index) as List).remove(e); - setState(() {}); - }, - child: filterWidget( - color: Colors.black, - icon: Icon( - Icons.calendar_today_outlined, - size: 15, - color: themeProvider.themeManager.placeholderTextColor, - ), - text: e, - ), - ) - : Container()) - .toList(), - ), - ], - )) - : const SizedBox())) + text: e, + ), + ) + : Container(); + }).toList(), + ), + ], + )) + : const SizedBox())) ], ), ), diff --git a/lib/screens/on_boarding/auth/sign_in.dart b/lib/screens/on_boarding/auth/sign_in.dart index 43bcab89..aa60fe64 100644 --- a/lib/screens/on_boarding/auth/sign_in.dart +++ b/lib/screens/on_boarding/auth/sign_in.dart @@ -288,7 +288,10 @@ class _SignInScreenState extends ConsumerState 'Source': 'Magic Code', 'Email': email.text, }, - ref: ref); + userEmail: profileProvider + .userProfile.email!, + userID: profileProvider + .userProfile.id!); Navigator.pushAndRemoveUntil( context, MaterialPageRoute( diff --git a/lib/utils/bottom_sheet.helper.dart b/lib/utils/bottom_sheet.helper.dart index 972ea653..a82ecb2e 100644 --- a/lib/utils/bottom_sheet.helper.dart +++ b/lib/utils/bottom_sheet.helper.dart @@ -13,7 +13,7 @@ class BottomSheetHelper { }) { showModalBottomSheet( constraints: constraints ?? - BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.7), + BoxConstraints(maxHeight: MediaQuery.sizeOf(context).height * 0.8), shape: shape ?? const RoundedRectangleBorder( borderRadius: BorderRadius.only( diff --git a/lib/utils/global_functions.dart b/lib/utils/global_functions.dart index 7c7af173..52f4b7f6 100644 --- a/lib/utils/global_functions.dart +++ b/lib/utils/global_functions.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/config/config_variables.dart'; import 'package:plane/main.dart'; -import 'package:plane/provider/provider_list.dart'; import 'package:posthog_flutter/posthog_flutter.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; @@ -22,13 +21,13 @@ void sentryService() { void postHogService( {required String eventName, required Map properties, - required WidgetRef ref}) { + required String userID, + required String userEmail}) { if (Config.posthogApiKey != null && Config.posthogApiKey != '') { - final profileProvider = ref.watch(ProviderList.profileProvider); properties.addAll( { - 'USER_ID': profileProvider.userProfile.id, - 'USER_EMAIL': profileProvider.userProfile.email, + 'USER_ID': userID, + 'USER_EMAIL': userEmail, }, ); try { diff --git a/lib/utils/issues_filter/group_by_issues.dart b/lib/utils/issues_filter/group_by_issues.dart index 7705219e..42ea03aa 100644 --- a/lib/utils/issues_filter/group_by_issues.dart +++ b/lib/utils/issues_filter/group_by_issues.dart @@ -1,4 +1,3 @@ - import 'package:plane/utils/enums.dart'; class IssuesGroupBYHelper { @@ -30,8 +29,7 @@ class IssuesGroupBYHelper { return groupedIssues; } - static Map> _groupByStateGroups( - List issues, Map states) { + static Map> _groupByStateGroups(List issues) { Map> groupedIssues = {}; for (final stateGroup in defaultStateGroups) { @@ -55,43 +53,41 @@ class IssuesGroupBYHelper { } static Map> _groupByLabels( - List issues, List labels) { + List issues, List labelIDs) { Map> groupedIssues = {}; - for (final label in labels) { + for (final label in labelIDs) { groupedIssues[label] = issues - .where((issue) => (issue['labels'] as List).contains(label)) + .where((issue) => (issue['label_ids'] as List).contains(label)) .toList(); } return groupedIssues; } static Map> _groupByAssignees( - List issues, List assignees) { + List issues, List memberIDs) { Map> groupedIssues = {}; - for (final assignee in assignees) { - groupedIssues[assignee['member']['id']] = issues - .where((issue) => - (issue['assignees'] as List).contains(assignee['member']['id'])) + for (final memberID in memberIDs) { + groupedIssues[memberID] = issues + .where((issue) => (issue['assignee_ids'] as List).contains(memberID)) .toList(); } return groupedIssues; } static Map> _groupByCreator( - List issues, List members) { + List issues, List memberIDs) { Map> groupedIssues = {}; - for (final member in members) { - groupedIssues[member['member']['id']] = issues - .where((issue) => (issue['created_by'] == member['member']['id'])) - .toList(); + for (final memberID in memberIDs) { + groupedIssues[memberID] = + issues.where((issue) => (issue['created_by'] == memberID)).toList(); } return groupedIssues; } static Map> _groupByProject( - List issues, List projects) { + List issues, List projectIDs) { Map> groupedIssues = {}; - for (final project in projects) { + for (final project in projectIDs) { groupedIssues[project['id']] = issues.where((issue) => (issue['project'] == project['id'])).toList(); } @@ -108,34 +104,33 @@ class IssuesGroupBYHelper { List issues, GroupBY groupBY, { Map? filter, - dynamic labels, - dynamic members, - dynamic projects, - dynamic states, + required List labelIDs, + required List memberIDs, + required dynamic stateIDs, }) { Map> groupedIssues = {}; switch (groupBY) { case GroupBY.state: - groupedIssues = _groupByState(issues, states); + groupedIssues = _groupByState(issues, stateIDs); break; case GroupBY.stateGroups: - groupedIssues = _groupByStateGroups(issues, states); + groupedIssues = _groupByStateGroups(issues); break; case GroupBY.priority: groupedIssues = _groupByPriority(issues); break; case GroupBY.labels: - groupedIssues = _groupByLabels(issues, labels); + groupedIssues = _groupByLabels(issues, labelIDs); break; case GroupBY.assignees: - groupedIssues = _groupByAssignees(issues, members); + groupedIssues = _groupByAssignees(issues, memberIDs); break; case GroupBY.createdBY: - groupedIssues = _groupByCreator(issues, members); - break; - case GroupBY.project: - groupedIssues = _groupByProject(issues, projects); + groupedIssues = _groupByCreator(issues, memberIDs); break; + // case GroupBY.project: + // groupedIssues = _groupByProject(issues, projectIDs); + // break; case GroupBY.none: groupedIssues = _groupByNone(issues); break; diff --git a/lib/utils/issues_filter/issue_filter.helper.dart b/lib/utils/issues_filter/issue_filter.helper.dart index dd5b4180..c60ea8d6 100644 --- a/lib/utils/issues_filter/issue_filter.helper.dart +++ b/lib/utils/issues_filter/issue_filter.helper.dart @@ -22,19 +22,17 @@ class IssueFilterHelper { GroupBY groupBY, OrderBY orderBY, { Map? filter, - dynamic labels, - dynamic members, - dynamic projects, - dynamic states, + required List labelIDs, + required List memberIDs, + required dynamic states, }) { Map> groupedIssues = IssuesGroupBYHelper.groupIssues( issues, groupBY, filter: filter, - labels: labels, - members: members, - projects: projects, - states: states, + labelIDs: labelIDs, + memberIDs: memberIDs, + stateIDs: states, ); Map organizedIssues = IssuesOrderBYHelper.orderIssues(groupedIssues, orderBY); diff --git a/lib/widgets/issue_card_widget.dart b/lib/widgets/issue_card_widget.dart index 6159b9e3..24771d89 100644 --- a/lib/widgets/issue_card_widget.dart +++ b/lib/widgets/issue_card_widget.dart @@ -1,18 +1,13 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:intl/intl.dart'; import 'package:plane/config/const.dart'; -import 'package:plane/provider/projects_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; - import 'package:plane/widgets/square_avatar_widget.dart'; - import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; import 'custom_rich_text.dart'; import 'custom_text.dart'; @@ -184,6 +179,7 @@ class _IssueCardWidgetState extends ConsumerState { final themeProvider = ref.read(ProviderList.themeProvider); dynamic provider; final projectProvider = ref.watch(ProviderList.projectProvider); + final labelProvider = ref.watch(ProviderList.labelProvider); if (widget.issueCategory == IssueCategory.cycleIssues) { provider = ref.watch(ProviderList.cyclesProvider); @@ -194,6 +190,8 @@ class _IssueCardWidgetState extends ConsumerState { } else { provider = ref.watch(ProviderList.issuesProvider); } + final issue = provider.issuesResponse[widget.cardIndex]; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -206,9 +204,7 @@ class _IssueCardWidgetState extends ConsumerState { widgets: [ TextSpan( text: projectProvider.currentProject['identifier']), - TextSpan( - text: - '-${provider.issuesResponse[widget.cardIndex]['sequence_id']}'), + TextSpan(text: '-${issue['sequence_id']}'), ], ), ) @@ -240,9 +236,7 @@ class _IssueCardWidgetState extends ConsumerState { ? Container( alignment: Alignment.center, decoration: BoxDecoration( - color: provider.issuesResponse[widget.cardIndex] - ['priority'] == - 'urgent' + color: issue['priority'] == 'urgent' ? Colors.red : null, border: Border.all( @@ -252,34 +246,28 @@ class _IssueCardWidgetState extends ConsumerState { margin: const EdgeInsets.only(right: 5), height: 30, width: 30, - child: provider.issuesResponse[widget.cardIndex]['priority'] == null || - provider.issuesResponse[widget.cardIndex] - ['priority'] == - 'none' + child: issue['priority'] == null || + issue['priority'] == 'none' ? Icon( Icons.do_disturb_alt_outlined, size: 18, color: themeProvider .themeManager.tertiaryTextColor, ) - : provider.issuesResponse[widget.cardIndex] - ['priority'] == - 'urgent' + : issue['priority'] == 'urgent' ? const Icon( Icons.error_outline_rounded, color: Colors.white, size: 18, ) - : provider.issuesResponse[widget.cardIndex] - ['priority'] == - 'high' + : issue['priority'] == 'high' ? const Icon( Icons.signal_cellular_alt, color: Color.fromRGBO(249, 115, 23, 1), size: 18, ) - : provider.issuesResponse[widget.cardIndex]['priority'] == 'medium' + : issue['priority'] == 'medium' ? const Icon( Icons.signal_cellular_alt_2_bar, color: Color.fromRGBO( @@ -296,19 +284,12 @@ class _IssueCardWidgetState extends ConsumerState { width: 0, ), provider.issues.displayProperties.assignee == true - ? (provider.issuesResponse[widget.cardIndex] - ['assignee_details'] != - null && - provider - .issuesResponse[widget.cardIndex] - ['assignee_details'] - .isNotEmpty) + ? (issue['assignee_details'] != null && + issue['assignee_details'].isNotEmpty) ? Container( margin: const EdgeInsets.only(right: 5), child: SquareAvatarWidget( - details: - provider.issuesResponse[widget.cardIndex] - ['assignee_details'], + details: issue['assignee_details'], ), ) : Container( @@ -333,12 +314,8 @@ class _IssueCardWidgetState extends ConsumerState { width: 0, ), (provider.issues.displayProperties.label == true && - provider - .issuesResponse[widget.cardIndex]['label_ids'] - .isNotEmpty) - ? provider.issuesResponse[widget.cardIndex]['label_ids'] - .length == - 1 + issue['label_ids'].isNotEmpty) + ? issue['label_ids'].length == 1 ? Container( width: 80, margin: const EdgeInsets.only(right: 5), @@ -357,18 +334,17 @@ class _IssueCardWidgetState extends ConsumerState { children: [ CircleAvatar( radius: 5, - backgroundColor: getLabelDetail( - provider.issuesResponse[ - widget.cardIndex] - ['label_ids'][0])['color'] - .toString() - .toColor(), + backgroundColor: + (labelProvider.projectLabels[ + issue['label_ids'][0]])! + .color + .toColor(), ), const SizedBox( width: 5, ), CustomText( - '${provider.issuesResponse[widget.cardIndex]['label_ids'].length} Labels', + '${issue['label_ids'].length} Labels', type: FontStyle.XSmall, height: 1, color: themeProvider @@ -384,11 +360,11 @@ class _IssueCardWidgetState extends ConsumerState { scrollDirection: Axis.horizontal, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, - itemCount: provider - .issuesResponse[widget.cardIndex] - ['label_ids'] - .length, + itemCount: issue['label_ids'].length, itemBuilder: (context, idx) { + final label = labelProvider + .projectLabels.values + .elementAt(idx); return Container( height: 30, padding: const EdgeInsets.only( @@ -407,14 +383,8 @@ class _IssueCardWidgetState extends ConsumerState { children: [ CircleAvatar( radius: 5, - backgroundColor: getLabelDetail( - provider.issuesResponse[ - widget - .cardIndex] - ['label_details'] - [idx])['color'] - .toString() - .toColor(), + backgroundColor: + label.color.toColor(), ), const SizedBox( width: 5, @@ -423,11 +393,7 @@ class _IssueCardWidgetState extends ConsumerState { constraints: const BoxConstraints( maxWidth: 120), child: CustomText( - getLabelDetail( - provider.issuesResponse[ - widget.cardIndex] - ['label_details'] - [idx])['name'], + label.name, type: FontStyle.XSmall, overflow: TextOverflow.ellipsis, maxLines: 1, @@ -459,15 +425,11 @@ class _IssueCardWidgetState extends ConsumerState { ), borderRadius: BorderRadius.circular(4)), child: CustomText( - provider.issuesResponse[widget.cardIndex] - ['start_date'] != - null + issue['start_date'] != null ? //convert yyyy-mm-dd to Aug 12, 2021 DateFormat('MMM dd, yyyy').format( - DateTime.parse(provider - .issuesResponse[widget.cardIndex] - ['start_date'])) + DateTime.parse(issue['start_date'])) : 'Start date', type: FontStyle.XSmall, height: 1, @@ -490,15 +452,11 @@ class _IssueCardWidgetState extends ConsumerState { .themeManager.borderSubtle01Color), borderRadius: BorderRadius.circular(4)), child: CustomText( - provider.issuesResponse[widget.cardIndex] - ['target_date'] != - null + issue['target_date'] != null ? //convert yyyy-mm-dd to Aug 12, 2021 DateFormat('MMM dd, yyyy').format( - DateTime.parse(provider - .issuesResponse[widget.cardIndex] - ['target_date'])) + DateTime.parse(issue['target_date'])) : 'Due date', type: FontStyle.XSmall, height: 1, @@ -537,17 +495,9 @@ class _IssueCardWidgetState extends ConsumerState { width: 5, ), CustomText( - provider.issuesResponse[widget.cardIndex] - ['sub_issues_count'] != - '' && - provider.issuesResponse[ - widget.cardIndex] - ['sub_issues_count'] != - null - ? provider - .issuesResponse[widget.cardIndex] - ['sub_issues_count'] - .toString() + issue['sub_issues_count'] != '' && + issue['sub_issues_count'] != null + ? issue['sub_issues_count'].toString() : '0', type: FontStyle.XSmall, height: 1, @@ -585,16 +535,9 @@ class _IssueCardWidgetState extends ConsumerState { width: 5, ), CustomText( - provider.issuesResponse[widget.cardIndex] - ['link_count'] != - '' && - provider.issuesResponse[widget - .cardIndex]['link_count'] != - null - ? provider - .issuesResponse[widget.cardIndex] - ['link_count'] - .toString() + issue['link_count'] != '' && + issue['link_count'] != null + ? issue['link_count'].toString() : '0', type: FontStyle.XSmall, height: 1, @@ -633,17 +576,9 @@ class _IssueCardWidgetState extends ConsumerState { width: 5, ), CustomText( - provider.issuesResponse[widget.cardIndex] - ['attachment_count'] != - '' && - provider.issuesResponse[ - widget.cardIndex] - ['attachment_count'] != - null - ? provider - .issuesResponse[widget.cardIndex] - ['attachment_count'] - .toString() + issue['attachment_count'] != '' && + issue['attachment_count'] != null + ? issue['attachment_count'].toString() : '0', type: FontStyle.XSmall, height: 1, @@ -683,13 +618,8 @@ class _IssueCardWidgetState extends ConsumerState { width: 5, ), CustomText( - provider.issuesResponse[widget.cardIndex] - ['estimate_point'] != - '' && - provider.issuesResponse[ - widget.cardIndex] - ['estimate_point'] != - null + issue['estimate_point'] != '' && + issue['estimate_point'] != null ? ref .read(ProviderList.estimatesProvider) .estimates @@ -699,8 +629,7 @@ class _IssueCardWidgetState extends ConsumerState { .currentProject['estimate']; })['points'].firstWhere((element) { return element['key'] == - provider.issuesResponse[widget - .cardIndex]['estimate_point']; + issue['estimate_point']; })['value'] : 'Estimate', type: FontStyle.XSmall, @@ -867,15 +796,4 @@ class _IssueCardWidgetState extends ConsumerState { ), ); } - - Map getLabelDetail(String issueId) { - final issuesProvider = ref.watch(ProviderList.issuesProvider); - Map? issueDetail; - for (final label in issuesProvider.labels) { - if (issueId == label['id']) { - log(issueId); - } - } - return issueDetail!; - } } diff --git a/pubspec.yaml b/pubspec.yaml index b4734e5f..69f68095 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -74,11 +74,14 @@ dependencies: dartz: ^0.10.1 upgrader: ^8.1.0 flutter_native_splash: ^2.3.2 + freezed_annotation: ^2.4.1 dev_dependencies: - build_runner: ^2.1.7 + freezed: ^2.4.6 + build_runner: ^2.4.8 + json_serializable: ^6.7.1 flutter_lints: ^2.0.0 - + flutter_test: sdk: flutter integration_test: diff --git a/test/providers/dashboard/dash_board_screen_test.dart b/test/providers/dashboard/dash_board_screen_test.dart index f2444a79..be0323ed 100644 --- a/test/providers/dashboard/dash_board_screen_test.dart +++ b/test/providers/dashboard/dash_board_screen_test.dart @@ -7,7 +7,7 @@ import 'package:mocktail/mocktail.dart'; import 'package:plane/bottom_sheets/global_search_sheet.dart'; import 'package:plane/bottom_sheets/select_workspace.dart'; import 'package:plane/models/user_profile_model.dart'; -import 'package:plane/models/workspace_model.dart'; +import 'package:plane/models/Workspace/workspace_model.dart'; import 'package:plane/provider/dashboard_provider.dart'; import 'package:plane/provider/profile_provider.dart'; import 'package:plane/provider/projects_provider.dart'; From 06e80b5cfe7060f03949cd86e7a2dc05d6aa0abb Mon Sep 17 00:00:00 2001 From: ramesh kumar Date: Tue, 23 Jan 2024 16:09:54 +0530 Subject: [PATCH 6/7] chore: state and labels model change, fix: cycles and modules issues fix, details pages fix, refactor: cycles and details ui refactor --- lib/bottom_sheets/filters/filter_sheet.dart | 18 +- .../filters/filter_sheet_state.dart | 26 +- .../filters/widgets/filter_buttons.dart | 9 +- lib/bottom_sheets/global_search_sheet.dart | 30 +- lib/bottom_sheets/views_sheet.dart | 42 +- lib/config/apis.dart | 3 + lib/kanban/Provider/board_provider.dart | 2 +- lib/models/Project/Label/label.model.dart | 15 +- lib/models/Project/State/states_model.dart | 38 +- lib/provider/cycles_provider.dart | 19 +- lib/provider/issue_provider.dart | 8 +- lib/provider/issues_provider.dart | 12 +- lib/provider/modules_provider.dart | 156 +- lib/provider/my_issues_provider.dart | 4 +- lib/provider/projects_provider.dart | 22 +- lib/repository/labels.service.dart | 8 +- lib/repository/profile_provider_service.dart | 2 +- lib/repository/projects_service.dart | 27 + lib/repository/states_service.dart | 30 +- lib/routers/generated_routes.dart | 6 +- .../MainScreens/Activity/activity.dart | 2 +- .../My_issues/my_issues_screen.dart | 2 +- .../Notification/notifications_list.dart | 2 +- .../profile_detail_screen.dart | 2 - .../Profile/User_profile/assigned_issues.dart | 2 +- .../User_profile/created_issue_page.dart.dart | 2 +- .../Profile/User_profile/over_view.dart | 9 +- .../User_profile/subscribed_issues.dart | 2 +- .../CycleDetail/cycle_details_page.dart | 713 +++++ .../Cycles/CycleDetail/cycle_issues_page.dart | 830 ++++++ .../{CyclesTab => Cycles}/create_cycle.dart | 0 .../cycle_active_card.dart | 2 +- .../project_details_cycles.dart | 4 +- .../CyclesTab/cycle_module_detail.dart | 2430 ----------------- .../Issue Layouts/List Layout/list_root.dart | 9 +- .../CreateIssue/create_issue.dart | 2 +- .../CreateIssue/selected_label_widget.dart | 0 .../{IssuesTab => Issues}/issue_detail.dart | 0 .../{IssuesTab => Issues}/issues_tab.dart | 0 .../ModuleDetail/module_detail_page.dart | 663 +++++ .../ModuleDetail/module_issues_page.dart | 822 ++++++ .../create_module.dart | 0 .../{ModulesTab => Modules}/module_card.dart | 5 +- .../module_screen.dart | 2 +- .../simple_module_card.dart | 6 +- .../{PagesTab => Pages}/page_block_card.dart | 0 .../{PagesTab => Pages}/page_card.dart | 2 +- .../{PagesTab => Pages}/page_detail.dart | 0 .../{PagesTab => Pages}/page_screen.dart | 2 +- .../ProjectDetail/Settings/create_label.dart | 17 +- .../Settings/estimates_page.dart | 2 - .../{ViewsTab => Views}/views.dart | 2 +- .../{ViewsTab => Views}/views_detail.dart | 2 +- .../ProjectDetail/archived_issues.dart | 2 +- .../Projects/ProjectDetail/calender_view.dart | 15 +- .../ProjectDetail/project_detail.dart | 4 +- .../ProjectDetail/spreadsheet_view.dart | 2 +- .../widgets/assignee_widget.dart | 78 + .../widgets/assignees_widget.dart | 118 + .../widgets/floating_action_button.dart | 4 +- .../ProjectDetail/widgets/links_widget.dart | 176 ++ .../ProjectDetail/widgets/progress_chart.dart | 96 + .../project_detail_bottom_actions.dart | 2 +- .../widgets/project_detail_root.dart | 15 +- .../ProjectDetail/widgets/states_widget.dart | 108 + .../Projects/create_project_screen.dart | 6 +- .../on_boarding/auth/setup_workspace.dart | 7 +- lib/screens/settings_screen.dart | 4 +- lib/utils/editor.dart | 2 +- lib/utils/issues_filter/group_by_issues.dart | 16 +- lib/widgets/empty.dart | 6 +- lib/widgets/issue_card_widget.dart | 50 +- 72 files changed, 4048 insertions(+), 2678 deletions(-) create mode 100644 lib/repository/projects_service.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_details_page.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart rename lib/screens/MainScreens/Projects/ProjectDetail/{CyclesTab => Cycles}/create_cycle.dart (100%) rename lib/screens/MainScreens/Projects/ProjectDetail/{CyclesTab => Cycles}/cycle_active_card.dart (99%) rename lib/screens/MainScreens/Projects/ProjectDetail/{CyclesTab => Cycles}/project_details_cycles.dart (99%) delete mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart rename lib/screens/MainScreens/Projects/ProjectDetail/{IssuesTab => Issues}/CreateIssue/create_issue.dart (99%) rename lib/screens/MainScreens/Projects/ProjectDetail/{IssuesTab => Issues}/CreateIssue/selected_label_widget.dart (100%) rename lib/screens/MainScreens/Projects/ProjectDetail/{IssuesTab => Issues}/issue_detail.dart (100%) rename lib/screens/MainScreens/Projects/ProjectDetail/{IssuesTab => Issues}/issues_tab.dart (100%) create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_detail_page.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart rename lib/screens/MainScreens/Projects/ProjectDetail/{ModulesTab => Modules}/create_module.dart (100%) rename lib/screens/MainScreens/Projects/ProjectDetail/{ModulesTab => Modules}/module_card.dart (99%) rename lib/screens/MainScreens/Projects/ProjectDetail/{ModulesTab => Modules}/module_screen.dart (99%) rename lib/screens/MainScreens/Projects/ProjectDetail/{ModulesTab => Modules}/simple_module_card.dart (98%) rename lib/screens/MainScreens/Projects/ProjectDetail/{PagesTab => Pages}/page_block_card.dart (100%) rename lib/screens/MainScreens/Projects/ProjectDetail/{PagesTab => Pages}/page_card.dart (99%) rename lib/screens/MainScreens/Projects/ProjectDetail/{PagesTab => Pages}/page_detail.dart (100%) rename lib/screens/MainScreens/Projects/ProjectDetail/{PagesTab => Pages}/page_screen.dart (98%) rename lib/screens/MainScreens/Projects/ProjectDetail/{ViewsTab => Views}/views.dart (99%) rename lib/screens/MainScreens/Projects/ProjectDetail/{ViewsTab => Views}/views_detail.dart (99%) create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/links_widget.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart create mode 100644 lib/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart diff --git a/lib/bottom_sheets/filters/filter_sheet.dart b/lib/bottom_sheets/filters/filter_sheet.dart index e4d47e72..0f9d2cf2 100644 --- a/lib/bottom_sheets/filters/filter_sheet.dart +++ b/lib/bottom_sheets/filters/filter_sheet.dart @@ -11,7 +11,6 @@ import 'package:plane/provider/cycles_provider.dart'; import 'package:plane/provider/modules_provider.dart'; import 'package:plane/provider/my_issues_provider.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/provider/states_provider.dart'; import 'package:plane/provider/theme_provider.dart'; import 'package:plane/screens/create_view_screen.dart'; import 'package:plane/utils/constants.dart'; @@ -72,14 +71,20 @@ class _FilterSheetState extends ConsumerState { setState(() {}); }, ref: ref); - super.initState(); } @override Widget build(BuildContext context) { final themeProvider = ref.watch(ProviderList.themeProvider); - + log(ref + .read(ProviderList.cyclesProvider) + .issues + .filters + .priorities + .toString()); + log(state.filters.priorities.toString()); + return Container( padding: const EdgeInsets.only(top: 20, left: 20, right: 20), child: Stack( @@ -161,10 +166,9 @@ class _FilterSheetState extends ConsumerState { ? Container() : _saveView(state: state, ref: ref), _applyFilterButton( - state: state, - context: context, - cycleOrModuleId: widget.cycleOrModuleId - ) + state: state, + context: context, + cycleOrModuleId: widget.cycleOrModuleId) ], ), ), diff --git a/lib/bottom_sheets/filters/filter_sheet_state.dart b/lib/bottom_sheets/filters/filter_sheet_state.dart index 5827d3e8..17c942f4 100644 --- a/lib/bottom_sheets/filters/filter_sheet_state.dart +++ b/lib/bottom_sheets/filters/filter_sheet_state.dart @@ -18,13 +18,27 @@ class _FilterState { isFilterDataEmpty = isFilterEmpty(tempFilters: myIssuesProvider.issues.filters); - } else { + } else if (issueCategory == IssueCategory.issues) { final issuesProvider = ref.read(ProviderList.issuesProvider); filters = Filters.fromJson(Filters.toJson(issuesProvider.issues.filters)); isFilterDataEmpty = isFilterEmpty(tempFilters: issuesProvider.issues.filters); + } else if (issueCategory == IssueCategory.cycleIssues) { + final cyclesProvider = ref.read(ProviderList.cyclesProvider); + filters = + Filters.fromJson(Filters.toJson(cyclesProvider.issues.filters)); + + isFilterDataEmpty = + isFilterEmpty(tempFilters: cyclesProvider.issues.filters); + } else if (issueCategory == IssueCategory.moduleIssues) { + final modulesProvider = ref.read(ProviderList.modulesProvider); + filters = + Filters.fromJson(Filters.toJson(modulesProvider.issues.filters)); + + isFilterDataEmpty = + isFilterEmpty(tempFilters: modulesProvider.issues.filters); } } else { filters = Filters.fromJson(filtersData["Filters"]); @@ -259,13 +273,13 @@ class _FilterState { ? modulesProvider.issues.filters = filters : issuesProvider.issues.filters = filters; if (issueCategory == IssueCategory.cycleIssues) { - // cyclesProvider.updateProjectView(); + cyclesProvider.updateCycleView(); cyclesProvider.filterCycleIssues( - slug: slug, projectId: projID, ref: ref, cycleID: cycleOrModuleId); + slug: slug, projectId: projID, cycleID: cycleOrModuleId, ref: ref); } else if (issueCategory == IssueCategory.moduleIssues) { - modulesProvider - .filterModuleIssues(slug: slug, projectId: projID, ref: ref) - .then((value) => modulesProvider.initializeBoard()); + modulesProvider.updateModuleView(); + modulesProvider.filterModuleIssues( + slug: slug, projectId: projID, ref: ref, moduleID: cycleOrModuleId); } else if (issueCategory == IssueCategory.myIssues) { myIssuesProvider.updateMyIssueView(); myIssuesProvider.filterIssues(); diff --git a/lib/bottom_sheets/filters/widgets/filter_buttons.dart b/lib/bottom_sheets/filters/widgets/filter_buttons.dart index c8b48cc2..1fdc8fc0 100644 --- a/lib/bottom_sheets/filters/widgets/filter_buttons.dart +++ b/lib/bottom_sheets/filters/widgets/filter_buttons.dart @@ -94,11 +94,10 @@ Widget _saveView({required _FilterState state, required WidgetRef ref}) { ); } -Widget _applyFilterButton({ - required _FilterState state, - required BuildContext context, - String? cycleOrModuleId -}) { +Widget _applyFilterButton( + {required _FilterState state, + required BuildContext context, + String? cycleOrModuleId}) { return Container( height: 50, width: state.fromCreateView || state.issueCategory == IssueCategory.myIssues diff --git a/lib/bottom_sheets/global_search_sheet.dart b/lib/bottom_sheets/global_search_sheet.dart index 8e4656db..00b2431b 100644 --- a/lib/bottom_sheets/global_search_sheet.dart +++ b/lib/bottom_sheets/global_search_sheet.dart @@ -12,11 +12,12 @@ import 'package:plane/provider/provider_list.dart'; import 'package:plane/screens/Import%20&%20Export/import_export.dart'; import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/members.dart'; import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/workspace_general.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/create_cycle.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ModulesTab/create_module.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/project_detail.dart'; import 'package:plane/screens/MainScreens/Projects/create_project_screen.dart'; import 'package:plane/screens/create_view_screen.dart'; @@ -28,7 +29,7 @@ import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; class GlobalSearchSheet extends ConsumerStatefulWidget { const GlobalSearchSheet({super.key}); @@ -1011,14 +1012,13 @@ class _GlobalSearchSheetState extends ConsumerState { Navigator.push( Const.globalKey.currentContext!, MaterialPageRoute( - builder: (context) => CycleDetail( + builder: (context) => ModuleDetail( moduleId: globalSearchProvider.data!.modules[index].id, moduleName: globalSearchProvider .data!.modules[index].name, projId: globalSearchProvider .data!.modules[index].projectId, - fromModule: true, ), ), ); @@ -1038,13 +1038,13 @@ class _GlobalSearchSheetState extends ConsumerState { width: 10, ), SizedBox( - width: width * 0.8, - child: CustomText( - globalSearchProvider - .data!.modules[index].name, - type: FontStyle.Medium, - maxLines: 2, - )), + width: width * 0.8, + child: CustomText( + globalSearchProvider.data!.modules[index].name, + type: FontStyle.Medium, + maxLines: 2, + ), + ), ], ), ), diff --git a/lib/bottom_sheets/views_sheet.dart b/lib/bottom_sheets/views_sheet.dart index 3d681cad..7281a1ef 100644 --- a/lib/bottom_sheets/views_sheet.dart +++ b/lib/bottom_sheets/views_sheet.dart @@ -15,12 +15,14 @@ class ViewsSheet extends ConsumerStatefulWidget { this.cycleId, this.fromView = false, this.isArchived = false, + this.moduleId, super.key, }); final Enum issueCategory; final IssueLayout projectView; final bool fromView; final String? cycleId; + final String? moduleId; final bool isArchived; @override @@ -783,7 +785,8 @@ class _ViewsSheetState extends ConsumerState { IssueCategory.moduleIssues) { modulesProvider.filterModuleIssues( slug: slug, - projectId: projID, ref: ref, + projectId: projID, + ref: ref, ); } else { issueProvider.filterIssues( @@ -827,10 +830,7 @@ class _ViewsSheetState extends ConsumerState { } else if (widget.issueCategory == IssueCategory.moduleIssues) { modulesProvider.filterModuleIssues( - slug: slug, - projectId: projID, - ref: ref - ); + slug: slug, projectId: projID, ref: ref); } else { issueProvider.filterIssues( fromViews: false, @@ -975,6 +975,12 @@ class _ViewsSheetState extends ConsumerState { cyclesProvider.applyCycleIssuesView(ref: ref); } else if (widget.issueCategory == IssueCategory.moduleIssues) { + setState(() { + modulesProvider.issues.groupBY = + Issues.toGroupBY(groupBy); + modulesProvider.issues.orderBY = + Issues.toOrderBY(orderBy); + }); modulesProvider.applyModuleIssuesView(ref: ref); } else { issueProvider.applyIssueView(); @@ -1011,23 +1017,25 @@ class _ViewsSheetState extends ConsumerState { // issueCategory: widget.issueCategory, // ); // cyclesProvider.issues.displayProperties = properties; - // cyclesProvider.showEmptyStates = showEmptyStates; + cyclesProvider.showEmptyStates = showEmptyStates; + cyclesProvider.updateCycleView(); } else if (widget.issueCategory == IssueCategory.moduleIssues) { - issueProvider.updateIssueProperties( - properties: properties, - issueCategory: widget.issueCategory, - ); - modulesProvider.issues.displayProperties = properties; + // issueProvider.updateIssueProperties( + // properties: properties, + // issueCategory: widget.issueCategory, + // ); + // modulesProvider.issues.displayProperties = properties; modulesProvider.showEmptyStates = showEmptyStates; + modulesProvider.updateModuleView(); } else { - issueProvider.updateIssueProperties( - properties: properties, - issueCategory: widget.issueCategory, - ); - issueProvider.issues.displayProperties = properties; - issueProvider.showEmptyStates = showEmptyStates; + // issueProvider.updateIssueProperties( + // properties: properties, + // issueCategory: widget.issueCategory, + // ); + // issueProvider.issues.displayProperties = properties; + // issueProvider.showEmptyStates = showEmptyStates; } if (widget.issueCategory == IssueCategory.issues) { issueProvider.updateProjectView(); diff --git a/lib/config/apis.dart b/lib/config/apis.dart index 6c60a236..0761e92b 100644 --- a/lib/config/apis.dart +++ b/lib/config/apis.dart @@ -45,6 +45,8 @@ class APIs { '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/project-members/me'; static String cycleIssueView = '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/cycles/\$CYCLEID/user-properties/'; + static String moduleIssueView = + '$baseApi/api/workspaces/\$SLUG/projects/\$PROJECTID/modules/\$MODULEID/user-properties/'; static String myIssuesView = '$baseApi/api/workspaces/\$SLUG/workspace-members/me/'; static String updateMyIssuesView = @@ -150,4 +152,5 @@ class APIs { static String retrieveUserRoleOnWorkspace = '$baseApi/api/workspaces/\$SLUG/workspace-members/me/'; static String configApi = '$baseApi/api/mobile-configs'; + static String unsplashApi = '$baseApi/api/unsplash'; } diff --git a/lib/kanban/Provider/board_provider.dart b/lib/kanban/Provider/board_provider.dart index 71a83914..ed9855e6 100644 --- a/lib/kanban/Provider/board_provider.dart +++ b/lib/kanban/Provider/board_provider.dart @@ -137,7 +137,7 @@ class BoardProvider extends ChangeNotifier { const SizedBox( width: 10, ), - data[i].leading!, + // data[i].leading!, const SizedBox( width: 10, ), diff --git a/lib/models/Project/Label/label.model.dart b/lib/models/Project/Label/label.model.dart index 4e19fef6..fa089d48 100644 --- a/lib/models/Project/Label/label.model.dart +++ b/lib/models/Project/Label/label.model.dart @@ -10,19 +10,12 @@ part 'label.model.g.dart'; @freezed class LabelModel with _$LabelModel { const factory LabelModel({ - required String id, - required DateTime created_at, - required DateTime updated_at, + String? parent, required String name, - required String description, required String color, - required String created_by, - required String updated_by, - required String project, - required ProjectLiteModel project_detail, - required String workspace, - required WorkspaceLiteModel workspace_detail, - String? parent, + required String id, + required String project_id, + required String workspace_id, required double sort_order, }) = _LabelModel; diff --git a/lib/models/Project/State/states_model.dart b/lib/models/Project/State/states_model.dart index 995d8041..f5226238 100644 --- a/lib/models/Project/State/states_model.dart +++ b/lib/models/Project/State/states_model.dart @@ -9,21 +9,15 @@ part 'states_model.g.dart'; class StatesModel with _$StatesModel { const factory StatesModel({ required final String id, - required final String created_at, - required final String updated_at, + required final String project_id, + required final String workspace_id, required final String name, - required final String? description, required final String color, - required final String slug, - required final double sequence, required final String group, - required final bool? is_default, - required final String? external_source, - required final String? external_id, - required final String created_by, - required final String? updated_by, - required final String project, - required final String workspace, + @JsonKey(name: 'default') + required final bool is_default, + required final String? description, + required final double sequence, @JsonKey(includeFromJson: false, includeToJson: false) Widget? stateIcon, }) = _StatesModel; @@ -32,23 +26,17 @@ class StatesModel with _$StatesModel { _$StatesModelFromJson(json); factory StatesModel.initialize() { - return const StatesModel( + return const StatesModel( id: '', - created_at: '', - updated_at: '', + project_id: '', + workspace_id: '', name: '', - description: '', color: '', - slug: '', - sequence: 0, group: '', is_default: false, - external_source: '', - external_id: '', - created_by: '', - updated_by: '', - project: '', - workspace: '', - stateIcon: null); + description: '', + sequence: 0, + stateIcon: null, + ); } } diff --git a/lib/provider/cycles_provider.dart b/lib/provider/cycles_provider.dart index 0751a057..790ec796 100644 --- a/lib/provider/cycles_provider.dart +++ b/lib/provider/cycles_provider.dart @@ -10,7 +10,7 @@ import 'package:plane/config/const.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; @@ -20,7 +20,7 @@ import 'package:plane/utils/issues_filter/issue_filter.helper.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; class CyclesProvider with ChangeNotifier { CyclesProvider(ChangeNotifierProviderRef this.ref); @@ -165,10 +165,6 @@ class CyclesProvider with ChangeNotifier { data: data, ); - // log('CYCLES =========> ${response.data.toString()}'); - - // * RESPONSE FROM API CONVERTED TO MODEL IS THROWING ERRORS FOR VIEW PROPS ATTRIBUTE * // - // cyclesData = CyclesModel.fromJson(response.data); if (query == 'all') { cyclesAllData = []; cycleFavoriteData = []; @@ -260,7 +256,7 @@ class CyclesProvider with ChangeNotifier { } } - void changeStateToLoading(StateEnum state) { + void changeState(StateEnum state) { state = StateEnum.loading; notifyListeners(); } @@ -294,7 +290,6 @@ class CyclesProvider with ChangeNotifier { : HttpMethod.patch, ); if (method == CRUD.read) { - // log('CYCLE DETAILS =========> ${response.data.toString()}'); cyclesDetailsData = response.data; } if (method == CRUD.update) { @@ -798,14 +793,12 @@ class CyclesProvider with ChangeNotifier { .replaceAll('\$PROJECTID', ref!.read(ProviderList.projectProvider).currentProject['id']) .replaceAll('\$CYCLEID', cycleId); - log('THIS IS CYCLE VIEW URL: $url'); final response = await DioConfig().dioServe( hasAuth: true, url: url, hasBody: false, httpMethod: HttpMethod.get, ); - log(response.toString()); cycleView = response.data; issues.projectView = cycleView['display_filters']['layout'] == 'list' ? IssueLayout.list @@ -898,7 +891,9 @@ class CyclesProvider with ChangeNotifier { .replaceAll('\$PROJECTID', projectId) .replaceAll('\$CYCLEID', cycleID!) .replaceAll('\$TYPE', Issues.fromIssueType(issues.issueType)); + url = '$url${IssueFilterHelper.getFilterQueryParams(issues.filters)}'; url = '$url&sub_issue=${issues.showSubIssues}&show_empty_groups=true'; + log(url.toString()); try { final response = await DioConfig().dioServe( hasAuth: true, @@ -906,7 +901,7 @@ class CyclesProvider with ChangeNotifier { hasBody: false, httpMethod: HttpMethod.get, ); - // log('CYCLE ISSUES RESPONSE: ${response.data}'); + // cycleIssuesList = []; cycleIssuesList = response.data; final organizedIssues = IssueFilterHelper.organizeIssues( cycleIssuesList, issues.groupBY, issues.orderBY, @@ -1015,7 +1010,7 @@ class CyclesProvider with ChangeNotifier { .replaceAll('\$CYCLEID', currentCycle['id']), hasBody: true, data: view, - httpMethod: HttpMethod.post, + httpMethod: HttpMethod.patch, ); cycleViewState = StateEnum.success; notifyListeners(); diff --git a/lib/provider/issue_provider.dart b/lib/provider/issue_provider.dart index e05c6c29..bf20be83 100644 --- a/lib/provider/issue_provider.dart +++ b/lib/provider/issue_provider.dart @@ -11,7 +11,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/config/config_variables.dart'; import 'package:plane/config/const.dart'; import 'package:plane/screens/MainScreens/Profile/User_profile/user_profile.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; @@ -19,7 +20,7 @@ import 'package:plane/config/apis.dart'; import 'package:plane/services/dio_service.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; +import '../screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; import '../utils/global_functions.dart'; // import 'package:webview_cookie_manager/webview_cookie_manager.dart'; @@ -619,9 +620,8 @@ class IssueProvider with ChangeNotifier { Navigator.push( context, MaterialPageRoute( - builder: (context) => CycleDetail( + builder: (context) => ModuleDetail( from: previousScreen, - fromModule: true, moduleId: data['module_id'], projId: data['project_id'], moduleName: data['module_name'], diff --git a/lib/provider/issues_provider.dart b/lib/provider/issues_provider.dart index 9652154c..7f9b5742 100644 --- a/lib/provider/issues_provider.dart +++ b/lib/provider/issues_provider.dart @@ -9,7 +9,7 @@ import 'package:plane/config/const.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; import 'package:plane/utils/global_functions.dart'; @@ -21,7 +21,7 @@ import 'package:plane/config/apis.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/enums.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; class IssuesProvider extends ChangeNotifier { IssuesProvider(ChangeNotifierProviderRef this.ref); @@ -328,9 +328,9 @@ class IssuesProvider extends ChangeNotifier { items: items, shrink: j >= shrinkStates.length ? false : shrinkStates[j], index: j, - width: issues.projectView == IssueLayout.list - ? MediaQuery.of(Const.globalKey.currentContext!).size.width - : (width > 500 ? 400 : width * 0.8), + // width: issues.projectView == IssueLayout.list + // ? MediaQuery.of(Const.globalKey.currentContext!).size.width + // : (width > 500 ? 400 : width * 0.8), // shrink: shrinkStates[count++], title: issues.groupBY == GroupBY.labels && label != null ? label.name[0].toString().toUpperCase() + @@ -374,7 +374,7 @@ class IssuesProvider extends ChangeNotifier { width: 10, ), SizedBox( - width: element.width - 150, + // width: element.width - 150, child: CustomText( element.title.toString(), type: FontStyle.Large, diff --git a/lib/provider/modules_provider.dart b/lib/provider/modules_provider.dart index 43a01a30..358c3e6c 100644 --- a/lib/provider/modules_provider.dart +++ b/lib/provider/modules_provider.dart @@ -7,7 +7,7 @@ import 'package:plane/config/apis.dart'; import 'package:plane/config/const.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; @@ -17,7 +17,7 @@ import 'package:plane/utils/global_functions.dart'; import 'package:plane/utils/issues_filter/issue_filter.helper.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; class ModuleProvider with ChangeNotifier { ModuleProvider(ChangeNotifierProviderRef this.ref); @@ -25,7 +25,6 @@ class ModuleProvider with ChangeNotifier { final modules = []; final favModules = []; Map createModule = {}; - int cycleDetailSelectedIndex = 0; Map moduleDetailsData = {}; List selectedIssues = []; int statusIndex = -1; @@ -70,6 +69,7 @@ class ModuleProvider with ChangeNotifier { Map filterIssues = {}; List moduleIssuesList = []; Map issueProperty = {}; + Map moduleView = {}; bool showEmptyStates = true; bool isIssuesEmpty = false; int moduleDetailSelectedIndex = 0; @@ -80,6 +80,7 @@ class ModuleProvider with ChangeNotifier { StateEnum moduleIssueState = StateEnum.loading; StateEnum deleteModuleState = StateEnum.empty; StateEnum moduleLinkState = StateEnum.empty; + StateEnum moduleViewState = StateEnum.empty; void changeIndex(int index) { statusIndex = index; @@ -106,6 +107,11 @@ class ModuleProvider with ChangeNotifier { notifyListeners(); } + void changeState(StateEnum state) { + state = StateEnum.loading; + notifyListeners(); + } + Future getModules( {required String slug, required String projId, @@ -402,6 +408,148 @@ class ModuleProvider with ChangeNotifier { } } + Future getModuleView({bool reset = false, required String moduleId}) async { + moduleViewState = StateEnum.loading; + if (reset) { + notifyListeners(); + } + try { + var url = APIs.moduleIssueView + .replaceAll( + "\$SLUG", + ref! + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug) + .replaceAll('\$PROJECTID', + ref!.read(ProviderList.projectProvider).currentProject['id']) + .replaceAll('\$MODULEID', moduleId); + final response = await DioConfig().dioServe( + hasAuth: true, + url: url, + hasBody: false, + httpMethod: HttpMethod.get, + ); + moduleView = response.data; + issues.projectView = moduleView['display_filters']['layout'] == 'list' + ? IssueLayout.list + : moduleView['display_filters']['layout'] == 'calendar' + ? IssueLayout.calendar + : moduleView['display_filters']['layout'] == 'spreadsheet' + ? IssueLayout.spreadsheet + : IssueLayout.kanban; + issues.showSubIssues = moduleView['display_filters']['sub_issue'] ?? true; + issues.groupBY = + Issues.toGroupBY(moduleView["display_filters"]["group_by"]); + issues.orderBY = + Issues.toOrderBY(moduleView["display_filters"]["order_by"]); + issues.issueType = + Issues.toIssueType(moduleView["display_filters"]["type"]); + issues.filters.priorities = + (moduleView["filters"]["priority"] == 'none' + ? [] + : moduleView["filters"]["priority"]) ?? + []; + issues.filters.states = moduleView["filters"]["state"] ?? []; + issues.filters.assignees = moduleView["filters"]["assignees"] ?? []; + issues.filters.createdBy = moduleView["filters"]["created_by"] ?? []; + issues.filters.labels = moduleView["filters"]["labels"] ?? []; + issues.filters.targetDate = moduleView["filters"]["target_date"] ?? []; + issues.filters.startDate = moduleView["filters"]["start_date"] ?? []; + issues.filters.subscriber = moduleView["filters"]["subscriber"] ?? []; + issues.filters.stateGroup = moduleView["filters"]["state_group"] ?? []; + showEmptyStates = moduleView["display_filters"]["show_empty_groups"]; + + if (issues.groupBY == GroupBY.none) { + issues.projectView = IssueLayout.list; + } + if (reset) { + updateModuleView(); + } + moduleViewState = StateEnum.success; + notifyListeners(); + } on DioException catch (e) { + log(e.response.toString()); + issues.projectView = IssueLayout.kanban; + moduleViewState = StateEnum.error; + notifyListeners(); + } + } + + Future updateModuleView( + {bool isArchive = false, bool setDefault = false}) async { + final Map view = { + "view_props": { + "calendarDateRange": "", + "collapsed": false, + "filterIssue": null, + "filters": { + // 'type': null, + // "priority": filterPriority, + if (issues.filters.priorities.isNotEmpty) + "priority": issues.filters.priorities, + if (issues.filters.states.isNotEmpty) "state": issues.filters.states, + if (issues.filters.assignees.isNotEmpty) + "assignees": issues.filters.assignees, + if (issues.filters.createdBy.isNotEmpty) + "created_by": issues.filters.createdBy, + if (issues.filters.labels.isNotEmpty) "labels": issues.filters.labels, + if (issues.filters.targetDate.isNotEmpty) + "target_date": issues.filters.targetDate, + if (issues.filters.startDate.isNotEmpty) + "start_date": issues.filters.startDate, + if (issues.filters.subscriber.isNotEmpty) + "subscriber": issues.filters.subscriber, + if (issues.filters.stateGroup.isNotEmpty) + "state_group": issues.filters.stateGroup, + }, + "display_filters": { + "group_by": Issues.fromGroupBY(issues.groupBY), + "order_by": Issues.fromOrderBY(issues.orderBY), + "type": Issues.fromIssueType(issues.issueType), + "show_empty_groups": showEmptyStates, + if (!isArchive) + "layout": issues.projectView == IssueLayout.kanban + ? 'kanban' + : issues.projectView == IssueLayout.list + ? 'list' + : issues.projectView == IssueLayout.calendar + ? 'calendar' + : 'spreadsheet', + "sub_issue": false, + }, + } + }; + if (setDefault) { + view['default_props'] = view['view_props']; + } + try { + await DioConfig().dioServe( + hasAuth: true, + url: APIs.moduleIssueView + .replaceAll( + "\$SLUG", + ref! + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug) + .replaceAll('\$PROJECTID', + ref!.read(ProviderList.projectProvider).currentProject['id']) + .replaceAll('\$MODULEID', currentModule['id']), + hasBody: true, + data: view, + httpMethod: HttpMethod.patch, + ); + moduleViewState = StateEnum.success; + notifyListeners(); + } on DioException catch (e) { + log(e.response.toString()); + moduleViewState = StateEnum.error; + notifyListeners(); + } + notifyListeners(); + } + void applyModuleIssuesView({required WidgetRef ref}) { final labelIds = ref.read(ProviderList.labelProvider.notifier).getLabelIds(); @@ -458,7 +606,7 @@ class ModuleProvider with ChangeNotifier { hasBody: false, httpMethod: HttpMethod.get, ); - moduleIssuesList = response.data.values.toList(); + moduleIssuesList = response.data; final organizedIssues = IssueFilterHelper.organizeIssues( moduleIssuesList, issues.groupBY, issues.orderBY, labelIDs: labelNotifier.getLabelIds(), diff --git a/lib/provider/my_issues_provider.dart b/lib/provider/my_issues_provider.dart index 761a8488..28feaf34 100644 --- a/lib/provider/my_issues_provider.dart +++ b/lib/provider/my_issues_provider.dart @@ -9,7 +9,7 @@ import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/profile_provider.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; //import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/constants.dart'; @@ -17,7 +17,7 @@ import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; class MyIssuesProvider extends ChangeNotifier { MyIssuesProvider(ChangeNotifierProviderRef this.ref); diff --git a/lib/provider/projects_provider.dart b/lib/provider/projects_provider.dart index 8570d19a..de1b1497 100644 --- a/lib/provider/projects_provider.dart +++ b/lib/provider/projects_provider.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/kanban/models/project_detail_model.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/repository/projects_service.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/config/apis.dart'; @@ -70,8 +71,7 @@ class ProjectsProvider extends ChangeNotifier { currentProject = {}; loadingProjectIndex = []; - coverUrl = - "https://app.plane.so/_next/image?url=https%3A%2F%2Fimages.unsplash.com%2Fphoto-1575116464504-9e7652fddcb3%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwyODUyNTV8MHwxfHNlYXJjaHwxOHx8cGxhbmV8ZW58MHx8fHwxNjgxNDY4NTY5%26ixlib%3Drb-4.0.3%26q%3D80%26w%3D1080&w=1920&q=75"; + coverUrl = ""; projectDetailModel = null; memberCount = 0; lead.clear(); @@ -102,7 +102,8 @@ class ProjectsProvider extends ChangeNotifier { .selectedWorkspace .workspaceSlug; - statesProvider.getStates(slug: workspaceSlug, projectId: currentProject['id']); + statesProvider.getStates( + slug: workspaceSlug, projectId: currentProject['id']); getProjectMembers( slug: workspaceSlug, projId: currentProject['id'], @@ -459,8 +460,6 @@ class ProjectsProvider extends ChangeNotifier { projectDetailModel!.projectLead = projectLead; final int index = currentProject["index"]; currentProject = projectDetailModel!.toJson(); - log('CURRENT PROJECT'); - log(currentProject.toString()); currentProject["index"] = index; projects[index]["name"] = currentProject["name"]; projects[index]["description"] = currentProject["description"]; @@ -678,4 +677,17 @@ class ProjectsProvider extends ChangeNotifier { } } + Future getUnsplashImages() async { + unsplashImageState = StateEnum.loading; + notifyListeners(); + final response = await ProjectsService().getUnspalshImages(); + response.fold((images) { + // unsplashImages = images; + unsplashImageState = StateEnum.success; + notifyListeners(); + }, (err) { + unsplashImageState = StateEnum.error; + notifyListeners(); + }); + } } diff --git a/lib/repository/labels.service.dart b/lib/repository/labels.service.dart index c0336d7d..02de22cc 100644 --- a/lib/repository/labels.service.dart +++ b/lib/repository/labels.service.dart @@ -52,7 +52,7 @@ class LabelsService { // CREATE Label Future> createLabel( - String slug, String projectID, Map payload) async { + String slug, String projectID, Map payload) async { try { final response = await dio.dioServe( hasAuth: true, @@ -71,7 +71,7 @@ class LabelsService { // UPDATE Label Future> updateLabel( - String slug, String projectID, Map payload) async { + String slug, String projectID, Map payload) async { try { final response = await dio.dioServe( hasAuth: true, @@ -79,7 +79,7 @@ class LabelsService { '${APIs.baseApi}/api/workspaces/$slug/projects/$projectID/issue-labels/${payload['id']}/', hasBody: true, data: payload, - httpMethod: HttpMethod.post, + httpMethod: HttpMethod.patch, ); return Left(LabelModel.fromJson(response.data)); } on DioException catch (err) { @@ -92,7 +92,7 @@ class LabelsService { Future> deleteLabel( String slug, String projectID, String labelID) async { try { - await dio.dioServe( + await dio.dioServe( hasAuth: true, url: '${APIs.baseApi}/api/workspaces/$slug/projects/$projectID/issue-labels/$labelID/', diff --git a/lib/repository/profile_provider_service.dart b/lib/repository/profile_provider_service.dart index 19d44601..0a126430 100644 --- a/lib/repository/profile_provider_service.dart +++ b/lib/repository/profile_provider_service.dart @@ -48,7 +48,7 @@ class ProfileService { try { final response = await dio.dioServe( hasAuth: true, - url: APIs.baseApi + APIs.profile, + url: APIs.profile, hasBody: true, httpMethod: HttpMethod.patch, data: data); diff --git a/lib/repository/projects_service.dart b/lib/repository/projects_service.dart new file mode 100644 index 00000000..478e6c69 --- /dev/null +++ b/lib/repository/projects_service.dart @@ -0,0 +1,27 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:dio/dio.dart'; +import 'package:plane/config/apis.dart'; +import 'package:plane/services/dio_service.dart'; +import 'package:plane/utils/enums.dart'; + +class ProjectsService { + final dio = DioConfig(); + + Future> getUnspalshImages() async { + try { + final response = await dio.dioServe( + hasAuth: true, + url: APIs.unsplashApi, + hasBody: false, + httpMethod: HttpMethod.get, + ); + log('UNSPLASH IMAGES: ${response.data}'); + return Left(response.data); + } on DioException catch (err) { + log(err.response.toString()); + return Right(err); + } + } +} diff --git a/lib/repository/states_service.dart b/lib/repository/states_service.dart index 588dce3d..f9b41a09 100644 --- a/lib/repository/states_service.dart +++ b/lib/repository/states_service.dart @@ -2,8 +2,6 @@ import 'dart:developer'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; import 'package:plane/config/apis.dart'; import 'package:plane/models/Project/State/states_model.dart'; import 'package:plane/services/dio_service.dart'; @@ -87,14 +85,12 @@ class StatesService { {required Map data, required String slug, required String projectId, - required String stateId - }) async { + required String stateId}) async { try { final response = await DioConfig().dioServe( hasAuth: true, - url: '${APIs.states - .replaceFirst('\$SLUG', slug) - .replaceFirst('\$PROJECTID', projectId)}$stateId/', + url: + '${APIs.states.replaceFirst('\$SLUG', slug).replaceFirst('\$PROJECTID', projectId)}$stateId/', hasBody: true, httpMethod: HttpMethod.patch, data: data); @@ -106,25 +102,21 @@ class StatesService { } Future> deleteState( - { - required String slug, + {required String slug, required String projectId, - required String stateId - }) async { + required String stateId}) async { try { final response = await DioConfig().dioServe( - hasAuth: true, - url: '${APIs.states - .replaceFirst('\$SLUG', slug) - .replaceFirst('\$PROJECTID', projectId)}$stateId/', - hasBody: true, - httpMethod: HttpMethod.delete, - ); + hasAuth: true, + url: + '${APIs.states.replaceFirst('\$SLUG', slug).replaceFirst('\$PROJECTID', projectId)}$stateId/', + hasBody: true, + httpMethod: HttpMethod.delete, + ); return Left(response.data); } on DioException catch (err) { log(err.response.toString()); return Right(err); } } - } diff --git a/lib/routers/generated_routes.dart b/lib/routers/generated_routes.dart index 0ceb7b89..cc3be09c 100644 --- a/lib/routers/generated_routes.dart +++ b/lib/routers/generated_routes.dart @@ -1,9 +1,9 @@ import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; import 'package:plane/screens/MainScreens/Activity/activity.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/create_cycle.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ModulesTab/create_module.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart'; import 'package:plane/screens/MainScreens/Projects/create_project_screen.dart'; import 'package:plane/screens/create_state.dart'; import 'package:plane/screens/home_screen.dart'; diff --git a/lib/screens/MainScreens/Activity/activity.dart b/lib/screens/MainScreens/Activity/activity.dart index 7bc642c4..412b7f20 100644 --- a/lib/screens/MainScreens/Activity/activity.dart +++ b/lib/screens/MainScreens/Activity/activity.dart @@ -16,7 +16,7 @@ import 'package:plane/widgets/error_state.dart'; import 'package:plane/widgets/loading_widget.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import '../Projects/ProjectDetail/Issues/issue_detail.dart'; class Activity extends ConsumerStatefulWidget { const Activity({super.key}); diff --git a/lib/screens/MainScreens/My_issues/my_issues_screen.dart b/lib/screens/MainScreens/My_issues/my_issues_screen.dart index 48cc3d83..d813da0f 100644 --- a/lib/screens/MainScreens/My_issues/my_issues_screen.dart +++ b/lib/screens/MainScreens/My_issues/my_issues_screen.dart @@ -7,7 +7,7 @@ import 'package:plane/bottom_sheets/views_and_layout_sheet.dart'; import 'package:plane/kanban/custom/board.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; diff --git a/lib/screens/MainScreens/Notification/notifications_list.dart b/lib/screens/MainScreens/Notification/notifications_list.dart index d493fd3f..f5225e8c 100644 --- a/lib/screens/MainScreens/Notification/notifications_list.dart +++ b/lib/screens/MainScreens/Notification/notifications_list.dart @@ -12,7 +12,7 @@ import 'package:plane/widgets/empty.dart'; import 'package:plane/widgets/error_state.dart'; import 'package:plane/widgets/loading_widget.dart'; -import '../Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import '../Projects/ProjectDetail/Issues/issue_detail.dart'; class NotificationsList extends ConsumerStatefulWidget { const NotificationsList({super.key, required this.data, required this.type}); diff --git a/lib/screens/MainScreens/Profile/ProfileSettings/profile_detail_screen.dart b/lib/screens/MainScreens/Profile/ProfileSettings/profile_detail_screen.dart index 88250e71..42ea362a 100644 --- a/lib/screens/MainScreens/Profile/ProfileSettings/profile_detail_screen.dart +++ b/lib/screens/MainScreens/Profile/ProfileSettings/profile_detail_screen.dart @@ -72,8 +72,6 @@ class _ProfileDetailScreenState extends ConsumerState { final themeProvider = ref.watch(ProviderList.themeProvider); final profileProvider = ref.watch(ProviderList.profileProvider); final fileUploadProvider = ref.watch(ProviderList.fileUploadProvider); - log('${profileProvider.userProfile.avatar} photo'); - log('profile : ${profileProvider.userProfile} '); return GestureDetector( onTap: () { FocusScope.of(context).unfocus(); diff --git a/lib/screens/MainScreens/Profile/User_profile/assigned_issues.dart b/lib/screens/MainScreens/Profile/User_profile/assigned_issues.dart index e46e640b..13c4bce6 100644 --- a/lib/screens/MainScreens/Profile/User_profile/assigned_issues.dart +++ b/lib/screens/MainScreens/Profile/User_profile/assigned_issues.dart @@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_rich_text.dart'; diff --git a/lib/screens/MainScreens/Profile/User_profile/created_issue_page.dart.dart b/lib/screens/MainScreens/Profile/User_profile/created_issue_page.dart.dart index b7739283..0cf8bd6c 100644 --- a/lib/screens/MainScreens/Profile/User_profile/created_issue_page.dart.dart +++ b/lib/screens/MainScreens/Profile/User_profile/created_issue_page.dart.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_rich_text.dart'; diff --git a/lib/screens/MainScreens/Profile/User_profile/over_view.dart b/lib/screens/MainScreens/Profile/User_profile/over_view.dart index 3636bb90..7f082990 100644 --- a/lib/screens/MainScreens/Profile/User_profile/over_view.dart +++ b/lib/screens/MainScreens/Profile/User_profile/over_view.dart @@ -6,8 +6,9 @@ import 'package:loading_indicator/loading_indicator.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:plane/config/const.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; @@ -470,8 +471,7 @@ class _OverViewScreenState extends ConsumerState { Navigator.push( Const.globalKey.currentContext!, MaterialPageRoute( - builder: (context) => CycleDetail( - fromModule: true, + builder: (context) => ModuleDetail( projId: userProfileProvider.userActivity .results![index].projectDetail!.id, moduleId: userProfileProvider.userActivity @@ -511,7 +511,6 @@ class _OverViewScreenState extends ConsumerState { Const.globalKey.currentContext!, MaterialPageRoute( builder: (context) => CycleDetail( - fromModule: false, projId: userProfileProvider.userActivity .results![index].projectDetail!.id, cycleId: userProfileProvider.userActivity diff --git a/lib/screens/MainScreens/Profile/User_profile/subscribed_issues.dart b/lib/screens/MainScreens/Profile/User_profile/subscribed_issues.dart index da3d7fcf..6df4ac73 100644 --- a/lib/screens/MainScreens/Profile/User_profile/subscribed_issues.dart +++ b/lib/screens/MainScreens/Profile/User_profile/subscribed_issues.dart @@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_rich_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_details_page.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_details_page.dart new file mode 100644 index 00000000..138414ec --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_details_page.dart @@ -0,0 +1,713 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:intl/intl.dart'; +import 'package:loading_indicator/loading_indicator.dart'; +import 'package:plane/bottom_sheets/assignee_sheet.dart'; +import 'package:plane/models/chart_model.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart'; +import 'package:plane/utils/constants.dart'; +import 'package:plane/utils/custom_toast.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/utils/extensions/string_extensions.dart'; +import 'package:plane/widgets/completion_percentage.dart'; +import 'package:plane/widgets/custom_text.dart'; +import 'package:plane/widgets/square_avatar_widget.dart'; + +class CycleDetailsPage extends ConsumerStatefulWidget { + const CycleDetailsPage( + {super.key, required this.cycleId, required this.chartData}); + final String cycleId; + final List chartData; + + @override + ConsumerState createState() => _CycleDetailsPageState(); +} + +class _CycleDetailsPageState extends ConsumerState { + DateTime? dueDate; + DateTime? startDate; + + @override + Widget build(BuildContext context) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final cyclesProvider = ref.watch(ProviderList.cyclesProvider); + + if (cyclesProvider.cyclesDetailState == StateEnum.loading) { + return Center( + child: SizedBox( + width: 30, + height: 30, + child: LoadingIndicator( + indicatorType: Indicator.lineSpinFadeLoader, + colors: [themeProvider.themeManager.primaryTextColor], + strokeWidth: 1.0, + backgroundColor: Colors.transparent, + ), + ), + ); + } else { + return ListView( + children: [ + const SizedBox(height: 30), + dateWidget(), + const SizedBox(height: 30), + detailsWidget(), + const SizedBox(height: 30), + progressWidget(ref: ref, chartData: widget.chartData), + const SizedBox(height: 30), + assigneesWidget(ref: ref, detailData: cyclesProvider.cyclesDetailsData), + const SizedBox(height: 30), + statesWidget(ref: ref, detailData: cyclesProvider.cyclesDetailsData), + const SizedBox(height: 30), + labelsWidget(), + const SizedBox(height: 30), + // widget.fromModule ? links() : Container() + ], + ); + } + } + + + Widget dateWidget() { + final cyclesProvider = ref.watch(ProviderList.cyclesProvider); + final themeProvider = ref.watch(ProviderList.themeProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + final detailData = cyclesProvider.cyclesDetailsData; + + startDate = DateFormat('yyyy-MM-dd').parse( + detailData['start_date'] == null || detailData['start_date'] == '' + ? DateTime.now().toString() + : detailData['start_date']!); + + dueDate = DateFormat('yyyy-MM-dd').parse( + detailData['end_date'] == null || detailData['end_date'] == '' + ? DateTime.now().toString() + : detailData['end_date']!); + + return Wrap( + runSpacing: 20, + children: [ + (detailData['start_date'] == null || detailData['start_date'] == '') || + (detailData['end_date'] == null || detailData['end_date'] == '') + ? Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + border: Border.all( + width: 1, + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: const CustomText( + 'Draft', + type: FontStyle.Small, + ), + ) + : Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date']) == + 'Draft' + ? themeProvider + .themeManager.tertiaryBackgroundDefaultColor + : checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date']) == + 'Completed' + ? themeProvider + .themeManager.secondaryBackgroundActiveColor + : themeProvider.themeManager.successBackgroundColor, + borderRadius: BorderRadius.circular(5)), + child: CustomText( + checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date'], + ), + type: FontStyle.Small, + color: checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date'], + ) == + 'Draft' + ? greyColor + : checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date'], + ) == + 'Completed' + ? themeProvider.themeManager.primaryColour + : greenHighLight, + ), + ), + const SizedBox(width: 20), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () async { + if (projectProvider.role != Role.admin && + projectProvider.role != Role.member) { + CustomToast.showToast(context, + message: accessRestrictedMSG, + toastType: ToastType.failure); + return; + } + final date = await showDatePicker( + builder: (context, child) => Theme( + data: themeProvider.themeManager.datePickerThemeData, + child: child!, + ), + context: context, + initialDate: startDate!, + firstDate: DateTime(2020), + lastDate: DateTime(2025), + ); + if (date != null) { + final bool dateNotConflicted = dueDate == null + ? true + : await cyclesProvider.dateCheck( + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: ref + .read(ProviderList.projectProvider) + .currentProject["id"], + data: { + "cycle_id": widget.cycleId, + "start_date": DateFormat('yyyy-MM-dd').format(date), + "end_date": + DateFormat('yyyy-MM-dd').format(dueDate!), + }, + ); + if (dateNotConflicted) { + if (dueDate != null && date.isAfter(dueDate!)) { + CustomToast.showToast(context, + message: 'Start date cannot be after end date', + toastType: ToastType.failure); + return; + } + setState(() { + startDate = date; + }); + } else { + CustomToast.showToast(context, + message: 'Date is conflicted with other cycle', + toastType: ToastType.failure); + return; + } + } + + if (date != null) { + cyclesProvider.cycleDetailsCrud( + disableLoading: true, + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: ref + .read(ProviderList.projectProvider) + .currentProject["id"], + method: CRUD.update, + cycleId: widget.cycleId, + data: {'start_date': DateFormat('yyyy-MM-dd').format(date)}, + ); + } + }, + child: Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: + themeProvider.themeManager.primaryBackgroundDefaultColor, + border: Border.all( + width: 1, + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: (detailData['start_date'] == null || + detailData['start_date'] == '') || + (detailData['end_date'] == null || + detailData['end_date'] == '') + ? CustomText( + 'Start Date', + type: FontStyle.Small, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.secondaryTextColor, + ) + : Row( + children: [ + Icon(Icons.calendar_today_outlined, + size: 15, + color: themeProvider + .themeManager.placeholderTextColor), + const SizedBox(width: 7), + CustomText( + '${dateFormating(detailData['start_date'])} ', + type: FontStyle.Small, + fontWeight: FontWeightt.Regular, + color: + themeProvider.themeManager.secondaryTextColor, + ), + ], + ), + ), + ), + //arrow + const SizedBox(width: 5), + Icon( + Icons.arrow_forward, + size: 15, + color: themeProvider.themeManager.placeholderTextColor, + ), + const SizedBox(width: 5), + GestureDetector( + onTap: () async { + if (projectProvider.role != Role.admin && + projectProvider.role != Role.member) { + CustomToast.showToast(context, + message: accessRestrictedMSG, + toastType: ToastType.failure); + return; + } + final date = await showDatePicker( + builder: (context, child) => Theme( + data: themeProvider.themeManager.datePickerThemeData, + child: child!, + ), + context: context, + initialDate: dueDate!, + firstDate: startDate ?? DateTime.now(), + lastDate: DateTime(2025), + ); + + if (date != null) { + if (!date.isAfter(DateTime.now())) { + CustomToast.showToast(context, + message: 'Due date not valid ', + toastType: ToastType.failure); + return; + } + if (date.isAfter(startDate!)) { + final bool dateNotConflicted = + await cyclesProvider.dateCheck( + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: ref + .read(ProviderList.projectProvider) + .currentProject["id"], + data: { + "cycle_id": widget.cycleId, + "start_date": + DateFormat('yyyy-MM-dd').format(startDate!), + "end_date": DateFormat('yyyy-MM-dd').format(date), + }, + ); + + if (dateNotConflicted) { + setState(() { + dueDate = date; + }); + cyclesProvider.cycleDetailsCrud( + disableLoading: true, + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: ref + .read(ProviderList.projectProvider) + .currentProject["id"], + method: CRUD.update, + cycleId: widget.cycleId, + data: { + 'end_date': DateFormat('yyyy-MM-dd').format(date) + }, + ); + cyclesProvider.changeTabIndex(1); + } else { + CustomToast.showToast(context, + message: 'Date is conflicted with other cycle ', + toastType: ToastType.failure); + } + } else { + CustomToast.showToast(context, + message: 'Start date cannot be after end date ', + toastType: ToastType.failure); + } + } + }, + child: Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: + themeProvider.themeManager.primaryBackgroundDefaultColor, + border: Border.all( + width: 1, + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: (detailData['start_date'] == null || + detailData['start_date'] == '') || + (detailData['end_date'] == null || + detailData['end_date'] == '') + ? CustomText('End Date', + type: FontStyle.Small, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.secondaryTextColor) + : Row( + children: [ + Icon(Icons.calendar_today_outlined, + size: 15, + color: themeProvider + .themeManager.placeholderTextColor), + const SizedBox(width: 5), + CustomText( + '${dateFormating(detailData['end_date'])} ', + type: FontStyle.Small, + fontWeight: FontWeightt.Regular, + color: themeProvider + .themeManager.secondaryTextColor), + ], + ), + ), + ), + ], + ), + ], + ); + } + + Widget detailsWidget() { + final themeProvider = ref.watch(ProviderList.themeProvider); + final cyclesProvider = ref.watch(ProviderList.cyclesProvider); + return Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: CustomText( + 'Details', + type: FontStyle.Medium, + fontWeight: FontWeightt.Medium, + color: themeProvider.themeManager.primaryTextColor, + )), + const SizedBox(height: 10), + stateWidget(), + const SizedBox(height: 10), + assigneeWidget(ref: ref, detailData: cyclesProvider.cyclesDetailsData), + ], + ); + } + + Widget labelsWidget({bool fromModule = false}) { + final cyclesProvider = ref.watch(ProviderList.cyclesProvider); + final issuesProvider = ref.watch(ProviderList.issuesProvider); + final themeProvider = ref.watch(ProviderList.themeProvider); + + final detailData = cyclesProvider.cyclesDetailsData; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.centerLeft, + child: CustomText( + 'Labels', + type: FontStyle.Medium, + fontWeight: FontWeightt.Medium, + color: themeProvider.themeManager.primaryTextColor, + )), + const SizedBox(height: 10), + detailData['distribution']['labels'].isNotEmpty + ? Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + decoration: BoxDecoration( + color: + themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: ListView.builder( + shrinkWrap: true, + primary: false, + itemCount: detailData['distribution']['labels'].length, + itemBuilder: (context, index) { + return Container( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 8), + margin: const EdgeInsets.symmetric(vertical: 2), + decoration: BoxDecoration( + color: issuesProvider.issues.filters.labels.contains( + detailData['distribution']['labels'][index] + ['label_id']) + ? themeProvider + .themeManager.secondaryBackgroundDefaultColor + : themeProvider + .themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Icon( + Icons.circle, + size: 20, + color: detailData['distribution']['labels'] + [index]['label_name'] == + null + ? themeProvider.themeManager + .tertiaryBackgroundDefaultColor + : detailData['distribution']['labels'] + [index]['color'] == + '' || + detailData['distribution'] + ['labels'][index] + ['color'] == + null + ? themeProvider + .themeManager.placeholderTextColor + : detailData['distribution']['labels'] + [index]['color'] + .toString() + .toColor(), + ), + const SizedBox( + width: 10, + ), + SizedBox( + width: width * 0.4, + child: CustomText( + detailData['distribution']['labels'][index] + ['label_name'] ?? + 'No Label', + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + Row( + children: [ + CompletionPercentage( + value: detailData['distribution']['labels'] + [index]['completed_issues'], + totalValue: detailData['distribution'] + ['labels'][index]['total_issues']) + ], + ) + ], + ), + ); + }), + ) + : const Align( + alignment: Alignment.center, + child: CustomText('No data found'), + ) + ], + ); + } + + Widget stateWidget({bool fromModule = false}) { + final cyclesProvider = ref.watch(ProviderList.cyclesProvider); + final themeProvider = ref.watch(ProviderList.themeProvider); + return Container( + height: 45, + width: double.infinity, + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: Padding( + padding: const EdgeInsets.only(left: 10, right: 10), + child: Row( + children: [ + //icon + Icon( + //four squares icon + Icons.timelapse_rounded, + color: themeProvider.themeManager.placeholderTextColor), + const SizedBox(width: 15), + CustomText( + 'Progress', + type: FontStyle.Medium, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.placeholderTextColor, + ), + Expanded(child: Container()), + + CompletionPercentage( + value: cyclesProvider.cyclesDetailsData['completed_issues'], + totalValue: cyclesProvider.cyclesDetailsData['total_issues'], + ) + ], + ), + ), + ); + } + + Widget membersWidget() { + final modulesProvider = ref.watch(ProviderList.modulesProvider); + final themeProvider = ref.watch(ProviderList.themeProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + return GestureDetector( + onTap: () { + if (projectProvider.role != Role.admin && + projectProvider.role != Role.member) { + CustomToast.showToast(context, + message: accessRestrictedMSG, toastType: ToastType.failure); + return; + } + showModalBottomSheet( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.5, + ), + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), + context: context, + builder: (context) => const AssigneeSheet( + fromModuleDetail: false, + ), + ); + }, + child: Container( + height: 45, + width: double.infinity, + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: Padding( + padding: const EdgeInsets.only(left: 10, right: 10), + child: Row( + children: [ + //icon + Icon( + //two people icon + Icons.people_alt_rounded, + color: themeProvider.themeManager.placeholderTextColor, + ), + const SizedBox(width: 15), + CustomText( + 'Members', + type: FontStyle.Medium, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.placeholderTextColor, + ), + Expanded(child: Container()), + (modulesProvider.currentModule['members_detail'] == null || + modulesProvider.currentModule['members_detail'].isEmpty) + ? Row( + children: [ + CustomText( + 'No members', + type: FontStyle.Medium, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.primaryTextColor, + ), + const SizedBox( + width: 5, + ), + Icon( + Icons.keyboard_arrow_down, + color: themeProvider.themeManager.primaryTextColor, + ), + ], + ) + : SizedBox( + height: 27, + child: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.center, + child: SizedBox( + height: 30, + child: SquareAvatarWidget( + borderRadius: 50, + details: modulesProvider + .currentModule['members_detail']), + ), + ), + ) + ], + ), + ), + ), + ); + } + + String dateFormating(String date) { + final DateTime formatedDate = DateTime.parse(date); + final String finalDate = DateFormat('dd MMM').format(formatedDate); + return finalDate; + } + + String checkDate({required String startDate, required String endDate}) { + final DateTime now = DateTime.now(); + if ((startDate.isEmpty) || (endDate.isEmpty)) { + return 'Draft'; + } else { + if (DateTime.parse(startDate).isAfter(now)) { + final Duration difference = + DateTime.parse(startDate.split('+').first).difference(now); + if (difference.inDays == 0) { + return 'Today'; + } else { + return '${difference.inDays.abs() + 1} Days Left'; + } + } + if (DateTime.parse(startDate).isBefore(now) && + DateTime.parse(endDate).isAfter(now)) { + final Duration difference = DateTime.parse(endDate).difference(now); + if (difference.inDays == 0) { + return 'Today'; + } else { + return '${difference.inDays.abs() + 1} Days Left'; + } + } else { + return 'Completed'; + } + } + } + + String checkTimeDifferenc(String dateTime) { + final DateTime now = DateTime.now(); + final Duration difference = now.difference(DateTime.parse(dateTime)); + String? format; + + if (difference.inDays > 0) { + format = '${difference.inDays} days ago'; + } else if (difference.inHours > 0) { + format = '${difference.inHours} hours ago'; + } else if (difference.inMinutes > 0) { + format = '${difference.inMinutes} minutes ago'; + } else { + format = '${difference.inSeconds} seconds ago'; + } + + return format; + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart new file mode 100644 index 00000000..d1b111dc --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart @@ -0,0 +1,830 @@ +// ignore_for_file: use_build_context_synchronously + +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:loading_indicator/loading_indicator.dart'; +import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom_sheets/type_sheet.dart'; +import 'package:plane/bottom_sheets/views_sheet.dart'; +import 'package:plane/kanban/custom/board.dart'; +import 'package:plane/kanban/models/inputs.dart'; +import 'package:plane/models/chart_model.dart'; +import 'package:plane/models/issues.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_details_page.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/calender_view.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart'; +import 'package:plane/utils/constants.dart'; +import 'package:plane/utils/custom_toast.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/custom_app_bar.dart'; +import 'package:plane/widgets/custom_text.dart'; +import 'package:plane/widgets/empty.dart'; +import '../../../../../../bottom_sheets/select_cycle_sheet.dart'; +import '../../Issues/issue_detail.dart'; + +class CycleDetail extends ConsumerStatefulWidget { + const CycleDetail( + {super.key, this.cycleId, this.cycleName, this.projId, this.from}); + final String? cycleName; + final String? cycleId; + final String? projId; + final PreviousScreen? from; + + @override + ConsumerState createState() => _CycleDetailState(); +} + +class _CycleDetailState extends ConsumerState { + List chartData = []; + PageController? pageController = PageController(); + List tempIssuesList = []; + + DateTime? dueDate; + DateTime? startDate; + + @override + void initState() { + final issuesProvider = ref.read(ProviderList.issuesProvider); + tempIssuesList = issuesProvider.issuesList; + issuesProvider.tempProjectView = issuesProvider.issues.projectView; + issuesProvider.tempGroupBy = issuesProvider.issues.groupBY; + issuesProvider.tempOrderBy = issuesProvider.issues.orderBY; + issuesProvider.tempIssueType = issuesProvider.issues.issueType; + issuesProvider.tempFilters = issuesProvider.issues.filters; + + issuesProvider.issues.projectView = IssueLayout.kanban; + issuesProvider.issues.groupBY = GroupBY.state; + + issuesProvider.issues.orderBY = OrderBY.lastCreated; + issuesProvider.issues.issueType = IssueType.all; + issuesProvider.showEmptyStates = true; + issuesProvider.issues.filters = Filters( + assignees: [], + createdBy: [], + labels: [], + priorities: [], + states: [], + targetDate: [], + startDate: [], + stateGroup: [], + subscriber: [], + ); + + WidgetsBinding.instance.addPostFrameCallback((_) async { + getCycleData(); + }); + super.initState(); + } + + Future getCycleData() async { + final cyclesProvider = ref.read(ProviderList.cyclesProvider); + final issuesProvider = ref.read(ProviderList.issuesProvider); + cyclesProvider.cyclesDetailState = StateEnum.loading; + pageController = PageController( + initialPage: cyclesProvider.cycleDetailSelectedIndex, + keepPage: true, + viewportFraction: 1); + + await cyclesProvider + .cycleDetailsCrud( + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: widget.projId ?? + ref.read(ProviderList.projectProvider).currentProject['id'], + method: CRUD.read, + disableLoading: true, + cycleId: widget.cycleId!) + .then((value) => getChartData(cyclesProvider + .cyclesDetailsData['distribution']['completion_chart'])); + + ref + .read(ProviderList.issuesProvider) + .getIssueDisplayProperties(issueCategory: IssueCategory.cycleIssues); + await cyclesProvider.getCycleView(cycleId: widget.cycleId!); + cyclesProvider + .filterCycleIssues( + cycleID: widget.cycleId!, + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: widget.projId ?? + ref.read(ProviderList.projectProvider).currentProject['id'], + ref: ref) + .then((value) { + if (issuesProvider.issues.projectView == IssueLayout.list) { + cyclesProvider.initializeBoard(); + } + }); + } + + Future getChartData(Map data) async { + data.forEach((key, value) { + chartData.add(ChartData(DateTime.parse(key), value != null ? value.toDouble() : 0)); + }); + } + + @override + Widget build(BuildContext context) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final cyclesProvider = ref.watch(ProviderList.cyclesProvider); + final cyclesProviderRead = ref.read(ProviderList.cyclesProvider.notifier); + final issueProvider = ref.watch(ProviderList.issuesProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + return WillPopScope( + onWillPop: () async { + return true; + }, + child: Scaffold( + floatingActionButton: cyclesProvider.cyclesIssueState == + StateEnum.loading && + (cyclesProvider.cyclesDetailsData['backlog_issues'] != 0 && + cyclesProvider.cyclesDetailsData['started_issues'] != 0 && + cyclesProvider.cyclesDetailsData['unstarted_issues'] != 0) + ? FloatingActionButton( + backgroundColor: themeProvider.themeManager.primaryColour, + onPressed: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: + BoxConstraints(maxHeight: height * 0.8, minHeight: 250), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + ), + ), + context: context, + builder: (ctx) { + return const SelectCycleSheet(); + }, + ); + }, + child: Container( + height: 50, + width: 50, + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryColour, + borderRadius: BorderRadius.circular(50), + ), + child: const Icon( + Icons.error_outline_outlined, + color: Colors.white, + ), + ), + ) + : null, + appBar: CustomAppBar( + centerTitle: true, + onPressed: () { + if (widget.from == PreviousScreen.myIssues) { + Navigator.pop(context); + return; + } + cyclesProvider.changeTabIndex(0); + cyclesProvider.changeState(StateEnum.empty); + Navigator.pop(context); + }, + text: widget.projId == null + ? projectProvider.currentProject['name'] + : projectProvider.projects.firstWhere( + (element) => element['id'] == widget.projId)['name'], + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 25, top: 20), + child: CustomText( + widget.cycleName!, + maxLines: 1, + type: FontStyle.H5, + fontWeight: FontWeightt.Semibold, + ), + ), + ), + ], + ), + SizedBox( + width: MediaQuery.of(context).size.width, + child: Row( + children: [ + Expanded( + child: InkWell( + onTap: () { + cyclesProvider.changeTabIndex(0); + pageController!.animateToPage( + 0, + duration: const Duration(milliseconds: 200), + curve: Curves.easeIn, + ); + }, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: CustomText( + overrride: true, + 'Issues', + type: FontStyle.Large, + fontWeight: FontWeightt.Medium, + color: + cyclesProviderRead.cycleDetailSelectedIndex == 1 + ? themeProvider + .themeManager.placeholderTextColor + : themeProvider.themeManager.primaryColour, + ), + ), + Container( + height: 7, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: + cyclesProviderRead.cycleDetailSelectedIndex == 0 + ? themeProvider.themeManager.primaryColour + : Colors.transparent, + ), + ), + ], + ), + )), + Expanded( + child: InkWell( + onTap: () { + cyclesProvider.changeTabIndex(1); + pageController!.animateToPage( + 1, + duration: const Duration(milliseconds: 200), + curve: Curves.easeIn, + ); + }, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: CustomText( + 'Details', + overrride: true, + type: FontStyle.Large, + fontWeight: FontWeightt.Medium, + color: + cyclesProviderRead.cycleDetailSelectedIndex == 0 + ? themeProvider + .themeManager.placeholderTextColor + : themeProvider.themeManager.primaryColour, + ), + ), + Container( + height: 7, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: + cyclesProviderRead.cycleDetailSelectedIndex == 1 + ? themeProvider.themeManager.primaryColour + : Colors.transparent, + ), + ), + ], + ), + )), + ], + ), + ), + Container( + height: 2, + width: MediaQuery.of(context).size.width, + color: themeProvider.themeManager.borderSubtle01Color, + ), + Expanded( + child: PageView( + controller: pageController, + onPageChanged: (value) { + if (value == 0) { + cyclesProvider.changeTabIndex(0); + } else { + cyclesProvider.changeTabIndex(1); + } + }, + children: [ + Column( + children: [ + Expanded( + child: + (cyclesProvider.cyclesIssueState == + StateEnum.loading || + cyclesProvider.cyclesDetailState == + StateEnum.loading) || + cyclesProvider.cycleViewState == + StateEnum.loading + ? Center( + child: SizedBox( + width: 30, + height: 30, + child: LoadingIndicator( + indicatorType: + Indicator.lineSpinFadeLoader, + colors: [ + themeProvider + .themeManager.primaryTextColor + ], + strokeWidth: 1.0, + backgroundColor: themeProvider + .themeManager + .primaryBackgroundDefaultColor, + )), + ) + : (cyclesProvider.isIssuesEmpty) + ? EmptyPlaceholder.emptyIssues(context, + cycleId: widget.cycleId, + projectId: widget.projId, + type: IssueCategory.cycleIssues, + ref: ref) + : (issueProvider.issues.projectView == + IssueLayout.list) + ? Container( + color: themeProvider.themeManager + .secondaryBackgroundDefaultColor, + margin: + const EdgeInsets.only(top: 5), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: cyclesProvider + .issues.issues + .map((state) => state + .items + .isEmpty && + !cyclesProvider + .showEmptyStates + ? Container() + : SizedBox( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Container( + padding: const EdgeInsets + .only( + left: + 15), + margin: const EdgeInsets + .only( + bottom: + 10), + child: Row( + children: [ + state.leading ?? + Container(), + Container( + padding: + const EdgeInsets.only( + left: + 10, + ), + width: + MediaQuery.of(context).size.width * 0.6, + child: + CustomText( + state.title!, + overflow: + TextOverflow.ellipsis, + maxLines: + 1, + type: + FontStyle.Small, + fontWeight: + FontWeightt.Medium, + ), + ), + Container( + alignment: + Alignment.center, + margin: + const EdgeInsets.only( + left: + 15, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: themeProvider.themeManager.secondaryBackgroundDefaultColor), + height: + 25, + width: + 30, + child: + CustomText( + state.items.length.toString(), + type: + FontStyle.Medium, + ), + ), + const Spacer(), + IconButton( + onPressed: + () { + if (issueProvider.issues.groupBY == GroupBY.state) { + issueProvider.createIssuedata['state'] = state.id; + } else { + issueProvider.createIssuedata['priority'] = 'de3c90cd-25cd-42ec-ac6c-a66caf8029bc'; + } + Navigator.of(context).push( + MaterialPageRoute( + builder: (ctx) => CreateIssue( + cycleId: widget.cycleId, + ), + ), + ); + }, + icon: + Icon( + Icons.add, + color: themeProvider.themeManager.primaryColour, + )), + const SizedBox( + width: + 10, + ), + ], + ), + ), + Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: state + .items + .map((e) => + e) + .toList()), + state.items + .isEmpty + ? Container( + margin: const EdgeInsets + .only( + bottom: 10), + width: MediaQuery.of(context) + .size + .width, + color: themeProvider + .themeManager + .primaryBackgroundDefaultColor, + padding: const EdgeInsets + .only( + top: 15, + bottom: 15, + left: 15), + child: + const CustomText( + 'No issues.', + type: + FontStyle.Small, + maxLines: + 10, + textAlign: + TextAlign.start, + ), + ) + : Container( + margin: const EdgeInsets + .only( + bottom: 10), + ) + ], + ), + )) + .toList()), + ), + ) + : issueProvider.issues.projectView == + IssueLayout.kanban + ? Padding( + padding: const EdgeInsets.only( + left: 8), + child: KanbanBoard( + cyclesProvider + .initializeBoard(), + boardID: 'cycle-board', + onItemReorder: ( + {newCardIndex, + newListIndex, + oldCardIndex, + oldListIndex}) { + cyclesProvider + .reorderIssue( + newCardIndex: + newCardIndex!, + newListIndex: + newListIndex!, + oldCardIndex: + oldCardIndex!, + oldListIndex: + oldListIndex!, + ) + .catchError( + (err) { + log(err.toString()); + CustomToast.showToast( + context, + message: + 'Failed to update issue', + toastType: + ToastType.failure, + ); + }, + ); + }, + isCardsDraggable: issueProvider + .checkIsCardsDaraggable(), + groupEmptyStates: + !cyclesProvider + .showEmptyStates, + cardPlaceHolderColor: + themeProvider.themeManager + .primaryBackgroundDefaultColor, + cardPlaceHolderDecoration: + BoxDecoration( + color: themeProvider + .themeManager + .primaryBackgroundDefaultColor, + boxShadow: [ + BoxShadow( + blurRadius: 2, + color: themeProvider + .themeManager + .borderSubtle01Color, + spreadRadius: 0, + ) + ], + ), + backgroundColor: themeProvider + .themeManager + .secondaryBackgroundDefaultColor, + listScrollConfig: + ScrollConfig( + offset: 65, + duration: const Duration( + milliseconds: 100, + ), + curve: Curves.linear, + ), + listTransitionDuration: + const Duration( + milliseconds: 200, + ), + cardTransitionDuration: + const Duration( + milliseconds: 400, + ), + textStyle: TextStyle( + fontSize: 19, + height: 1.3, + color: Colors.grey.shade800, + fontWeight: FontWeight.w500, + ), + ), + ) + : issueProvider + .issues.projectView == + IssueLayout.calendar + ? const CalendarView() + : const SpreadSheetView( + issueCategory: IssueCategory + .cycleIssues, + ), + ), + SafeArea( + child: Container( + height: 50, + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + color: themeProvider + .themeManager.primaryBackgroundDefaultColor, + boxShadow: themeProvider + .themeManager.shadowBottomControlButtons), + child: Row( + children: [ + projectProvider.role == Role.admin || + projectProvider.role == Role.member + ? Expanded( + child: GestureDetector( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => CreateIssue( + projectId: widget.projId ?? + projectProvider + .currentProject['id'], + fromMyIssues: true, + cycleId: widget.cycleId, + ), + ), + ); + }, + child: SizedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.add, + color: themeProvider + .themeManager + .primaryTextColor, + size: 20, + ), + const CustomText( + ' Issue', + type: FontStyle.Medium, + ) + ], + ), + ), + ), + ) + : Container(), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + Expanded( + child: GestureDetector( + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context) + .size + .height * + 0.85), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + )), + context: context, + builder: (ctx) { + return const TypeSheet( + issueCategory: + IssueCategory.cycleIssues, + ); + }); + }, + child: SizedBox( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.menu, + color: themeProvider + .themeManager.primaryTextColor, + size: 19, + ), + const CustomText( + ' Layout', + type: FontStyle.Medium, + ) + ], + ), + ), + )), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + issueProvider.issues.projectView == + IssueLayout.calendar + ? Container() + : Expanded( + child: GestureDetector( + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: BoxConstraints( + maxHeight: + MediaQuery.of(context) + .size + .height * + 0.9), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + )), + context: context, + builder: (ctx) { + return ViewsSheet( + projectView: issueProvider + .issues.projectView, + issueCategory: + IssueCategory.cycleIssues, + cycleId: widget.cycleId, + ); + }); + }, + child: SizedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.wysiwyg_outlined, + color: themeProvider.themeManager + .primaryTextColor, + size: 19, + ), + const CustomText( + ' Display', + type: FontStyle.Medium, + ) + ], + ), + ), + )), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + Expanded( + child: GestureDetector( + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context) + .size + .height * + 0.85), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + )), + context: context, + builder: (ctx) { + return FilterSheet( + issueCategory: + IssueCategory.cycleIssues, + cycleOrModuleId: widget.cycleId, + ); + }); + }, + child: SizedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.filter_list_outlined, + color: themeProvider + .themeManager.primaryTextColor, + size: 19, + ), + const CustomText( + ' Filters', + type: FontStyle.Medium, + ) + ], + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + CycleDetailsPage( + cycleId: widget.cycleId!, + chartData: chartData, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/create_cycle.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/create_cycle.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_active_card.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/cycle_active_card.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_active_card.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Cycles/cycle_active_card.dart index 642f5db5..5f2969ad 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_active_card.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/cycle_active_card.dart @@ -7,7 +7,7 @@ import 'package:plane/models/chart_model.dart'; import 'package:plane/provider/cycles_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/extensions/list_extensions.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/project_details_cycles.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/project_details_cycles.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart index 4b97c6ff..7fc7bd30 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/project_details_cycles.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_active_card.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/cycle_active_card.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart deleted file mode 100644 index b5e408ef..00000000 --- a/lib/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart +++ /dev/null @@ -1,2430 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'dart:developer'; - -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:intl/intl.dart'; -import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/assignee_sheet.dart'; -import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; -import 'package:plane/bottom_sheets/lead_sheet.dart'; -import 'package:plane/bottom_sheets/type_sheet.dart'; -import 'package:plane/bottom_sheets/views_sheet.dart'; -import 'package:plane/kanban/custom/board.dart'; -import 'package:plane/kanban/models/inputs.dart'; -import 'package:plane/models/chart_model.dart'; -import 'package:plane/models/issues.dart'; -import 'package:plane/provider/modules_provider.dart'; -import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/calender_view.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart'; -import 'package:plane/utils/constants.dart'; -import 'package:plane/utils/custom_toast.dart'; -import 'package:plane/utils/enums.dart'; -import 'package:plane/utils/extensions/string_extensions.dart'; -import 'package:plane/widgets/completion_percentage.dart'; -import 'package:plane/widgets/custom_app_bar.dart'; -import 'package:plane/widgets/custom_text.dart'; -import 'package:plane/widgets/empty.dart'; -import 'package:plane/widgets/member_logo_widget.dart'; -import 'package:plane/widgets/square_avatar_widget.dart'; -import 'package:syncfusion_flutter_charts/charts.dart'; - -import '../../../../../bottom_sheets/add_link_sheet.dart'; -import '../../../../../bottom_sheets/select_cycle_sheet.dart'; -import '../IssuesTab/issue_detail.dart'; - -class CycleDetail extends ConsumerStatefulWidget { - const CycleDetail( - {super.key, - this.cycleId, - this.cycleName, - this.moduleId, - this.moduleName, - this.fromModule = false, - this.projId, - this.from}); - final String? cycleName; - final String? cycleId; - final String? moduleName; - final String? moduleId; - final String? projId; - final bool fromModule; - final PreviousScreen? from; - - @override - ConsumerState createState() => _CycleDetailState(); -} - -class _CycleDetailState extends ConsumerState { - List chartData = []; - PageController? pageController = PageController(); - List tempIssuesList = []; - - DateTime? dueDate; - DateTime? startDate; - - @override - void initState() { - final issuesProvider = ref.read(ProviderList.issuesProvider); - tempIssuesList = issuesProvider.issuesList; - issuesProvider.tempProjectView = issuesProvider.issues.projectView; - issuesProvider.tempGroupBy = issuesProvider.issues.groupBY; - issuesProvider.tempOrderBy = issuesProvider.issues.orderBY; - issuesProvider.tempIssueType = issuesProvider.issues.issueType; - issuesProvider.tempFilters = issuesProvider.issues.filters; - - issuesProvider.issues.projectView = IssueLayout.kanban; - issuesProvider.issues.groupBY = GroupBY.state; - - issuesProvider.issues.orderBY = OrderBY.lastCreated; - issuesProvider.issues.issueType = IssueType.all; - issuesProvider.showEmptyStates = true; - issuesProvider.issues.filters = Filters( - assignees: [], - createdBy: [], - labels: [], - priorities: [], - states: [], - targetDate: [], - startDate: [], - stateGroup: [], - subscriber: [], - ); - - WidgetsBinding.instance.addPostFrameCallback((_) async { - if (widget.fromModule) { - getModuleData(); - } else { - getCycleData(); - } - }); - super.initState(); - } - - Future getModuleData() async { - final modulesProvider = ref.read(ProviderList.modulesProvider); - final issuesProvider = ref.read(ProviderList.issuesProvider); - - pageController = PageController( - initialPage: modulesProvider.moduleDetailSelectedIndex, - keepPage: true, - viewportFraction: 1); - - await modulesProvider - .getModuleDetails( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projId: ref.read(ProviderList.projectProvider).currentProject['id'], - moduleId: widget.moduleId!, - disableLoading: true) - .then((value) => getChartData(modulesProvider - .moduleDetailsData['distribution']['completion_chart'])); - issuesProvider.getIssueDisplayProperties( - issueCategory: IssueCategory.moduleIssues); - modulesProvider - .filterModuleIssues( - moduleID: widget.moduleId, - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: - ref.read(ProviderList.projectProvider).currentProject['id'], - ref: ref) - .then((value) { - if (modulesProvider.issues.projectView == IssueLayout.list) { - modulesProvider.initializeBoard(); - } - }); - } - - Future getCycleData() async { - final cyclesProvider = ref.read(ProviderList.cyclesProvider); - final issuesProvider = ref.read(ProviderList.issuesProvider); - cyclesProvider.cyclesDetailState = StateEnum.loading; - pageController = PageController( - initialPage: cyclesProvider.cycleDetailSelectedIndex, - keepPage: true, - viewportFraction: 1); - - await cyclesProvider - .cycleDetailsCrud( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: widget.projId ?? - ref.read(ProviderList.projectProvider).currentProject['id'], - method: CRUD.read, - disableLoading: true, - cycleId: widget.cycleId!) - .then((value) => getChartData(cyclesProvider - .cyclesDetailsData['distribution']['completion_chart'])); - - ref - .read(ProviderList.issuesProvider) - .getIssueDisplayProperties(issueCategory: IssueCategory.cycleIssues); - await cyclesProvider - .getCycleView(cycleId: widget.cycleId!); - cyclesProvider - .filterCycleIssues( - cycleID: widget.cycleId!, - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: widget.projId ?? - ref.read(ProviderList.projectProvider).currentProject['id'], - ref: ref) - .then((value) { - if (issuesProvider.issues.projectView == IssueLayout.list) { - cyclesProvider.initializeBoard(); - } - }); - } - - Future getChartData(Map data) async { - data.forEach((key, value) { - chartData.add(ChartData(DateTime.parse(key), value.toDouble())); - }); - } - - @override - Widget build(BuildContext context) { - final themeProvider = ref.watch(ProviderList.themeProvider); - final cyclesProvider = ref.watch(ProviderList.cyclesProvider); - final cyclesProviderRead = ref.read(ProviderList.cyclesProvider); - final issueProvider = ref.watch(ProviderList.issuesProvider); - final modulesProvider = ref.watch(ProviderList.modulesProvider); - final projectProvider = ref.read(ProviderList.projectProvider); - final bool isLoading = widget.fromModule - ? modulesProvider.moduleState == StateEnum.loading - : cyclesProvider.cyclesState == StateEnum.loading; - return WillPopScope( - onWillPop: () async { - if (widget.from == PreviousScreen.myIssues) return true; - modulesProvider.selectedIssues = []; - cyclesProvider.selectedIssues = []; - issueProvider.issues.projectView = issueProvider.tempProjectView; - issueProvider.issues.groupBY = issueProvider.tempGroupBy; - - issueProvider.issues.orderBY = issueProvider.tempOrderBy; - issueProvider.issues.issueType = issueProvider.tempIssueType; - - issueProvider.issues.filters = issueProvider.tempFilters; - - issueProvider.showEmptyStates = - issueProvider.issueView['display_filters']["show_empty_groups"]; - - issueProvider.setsState(); - issueProvider.filterIssues( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: projectProvider.currentProject['id']); - return true; - }, - child: Scaffold( - floatingActionButton: isLoading && - !widget.fromModule && - DateTime.parse(cyclesProvider.cyclesDetailsData['end_date']) - .isBefore(DateTime.now()) && - (cyclesProvider.cyclesDetailsData['backlog_issues'] != 0 && - cyclesProvider.cyclesDetailsData['started_issues'] != 0 && - cyclesProvider.cyclesDetailsData['unstarted_issues'] != 0) - ? FloatingActionButton( - backgroundColor: themeProvider.themeManager.primaryColour, - onPressed: () { - showModalBottomSheet( - isScrollControlled: true, - enableDrag: true, - constraints: BoxConstraints( - maxHeight: height * 0.8, minHeight: 250), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(30), - topRight: Radius.circular(30), - )), - context: context, - builder: (ctx) { - return const SelectCycleSheet(); - }); - }, - child: Container( - height: 50, - width: 50, - decoration: BoxDecoration( - color: themeProvider.themeManager.primaryColour, - borderRadius: BorderRadius.circular(50), - ), - child: const Icon( - Icons.error_outline_outlined, - color: Colors.white, - ), - ), - ) - : null, - appBar: CustomAppBar( - centerTitle: true, - onPressed: () { - if (widget.from == PreviousScreen.myIssues) { - Navigator.pop(context); - return; - } - if (widget.fromModule) { - modulesProvider.changeTabIndex(0); - } else { - cyclesProvider.changeTabIndex(0); - } - modulesProvider.selectedIssues = []; - cyclesProvider.selectedIssues = []; - issueProvider.issues.projectView = issueProvider.tempProjectView; - issueProvider.issues.groupBY = issueProvider.tempGroupBy; - - issueProvider.issues.orderBY = issueProvider.tempOrderBy; - issueProvider.issues.issueType = issueProvider.tempIssueType; - - issueProvider.issues.filters = issueProvider.tempFilters; - issueProvider.showEmptyStates = - issueProvider.issueView['display_filters'] != null - ? issueProvider.issueView['display_filters'] - ["show_empty_groups"] - : false; - - issueProvider.setsState(); - issueProvider.filterIssues( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projID: projectProvider.currentProject['id']); - Navigator.pop(context); - }, - text: widget.projId == null - ? projectProvider.currentProject['name'] - : projectProvider.projects.firstWhere( - (element) => element['id'] == widget.projId)['name'], - ), - body: isLoading - ? Center( - child: SizedBox( - width: 30, - height: 30, - child: LoadingIndicator( - indicatorType: Indicator.lineSpinFadeLoader, - colors: [themeProvider.themeManager.primaryTextColor], - strokeWidth: 1.0, - backgroundColor: Colors.transparent, - )), - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 25, top: 20), - child: CustomText( - widget.fromModule - ? widget.moduleName! - : widget.cycleName!, - maxLines: 1, - type: FontStyle.H5, - fontWeight: FontWeightt.Semibold, - ), - ), - ), - ], - ), - SizedBox( - width: MediaQuery.of(context).size.width, - child: Row( - children: [ - Expanded( - child: InkWell( - onTap: () { - widget.fromModule - ? { - modulesProvider.changeTabIndex(0), - pageController!.animateToPage(0, - duration: - const Duration(milliseconds: 100), - curve: Curves.easeIn) - } - : { - cyclesProvider.changeTabIndex(0), - pageController!.animateToPage(0, - duration: - const Duration(milliseconds: 100), - curve: Curves.easeIn) - }; - }, - child: Column( - children: [ - Padding( - padding: - const EdgeInsets.symmetric(vertical: 10), - child: CustomText( - overrride: true, - 'Issues', - type: FontStyle.Large, - fontWeight: FontWeightt.Medium, - color: (widget.fromModule - ? modulesProvider - .moduleDetailSelectedIndex == - 1 - : cyclesProviderRead - .cycleDetailSelectedIndex == - 1) - ? themeProvider - .themeManager.placeholderTextColor - : (widget.fromModule - ? modulesProvider - .moduleDetailSelectedIndex == - 1 - : cyclesProviderRead - .cycleDetailSelectedIndex == - 1) - ? themeProvider - .themeManager.placeholderTextColor - : themeProvider - .themeManager.primaryColour, - ), - ), - Container( - height: 7, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: (widget.fromModule - ? modulesProvider - .moduleDetailSelectedIndex == - 0 - : cyclesProviderRead - .cycleDetailSelectedIndex == - 0) - ? themeProvider.themeManager.primaryColour - : Colors.transparent, - ), - ), - ], - ), - )), - Expanded( - child: InkWell( - onTap: () { - widget.fromModule - ? { - modulesProvider.changeTabIndex(1), - pageController!.animateToPage(1, - duration: - const Duration(milliseconds: 100), - curve: Curves.easeIn) - } - : { - cyclesProvider.changeTabIndex(1), - pageController!.animateToPage(1, - duration: - const Duration(milliseconds: 100), - curve: Curves.easeIn) - }; - }, - child: Column( - children: [ - Padding( - padding: - const EdgeInsets.symmetric(vertical: 10), - child: CustomText('Details', - overrride: true, - type: FontStyle.Large, - fontWeight: FontWeightt.Medium, - color: (widget.fromModule - ? modulesProvider - .moduleDetailSelectedIndex == - 0 - : cyclesProviderRead - .cycleDetailSelectedIndex == - 0) - ? themeProvider - .themeManager.placeholderTextColor - : (widget.fromModule - ? modulesProvider - .moduleDetailSelectedIndex == - 0 - : cyclesProviderRead - .cycleDetailSelectedIndex == - 0) - ? themeProvider.themeManager - .placeholderTextColor - : themeProvider - .themeManager.primaryColour), - ), - Container( - height: 7, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: (widget.fromModule - ? modulesProvider - .moduleDetailSelectedIndex == - 1 - : cyclesProviderRead - .cycleDetailSelectedIndex == - 1) - ? themeProvider.themeManager.primaryColour - : Colors.transparent, - ), - ), - ], - ), - )), - ], - ), - ), - Container( - height: 2, - width: MediaQuery.of(context).size.width, - color: themeProvider.themeManager.borderSubtle01Color, - ), - Expanded( - child: PageView( - controller: pageController, - onPageChanged: (value) { - if (value == 0) { - widget.fromModule - ? modulesProvider.changeTabIndex(0) - : cyclesProvider.changeTabIndex(0); - } else { - widget.fromModule - ? modulesProvider.changeTabIndex(1) - : cyclesProvider.changeTabIndex(1); - } - }, - children: [ - Column( - children: [ - Expanded( - child: - ((widget.fromModule && (modulesProvider.moduleIssueState == StateEnum.loading || modulesProvider.moduleDetailState == StateEnum.loading)) || - (!widget.fromModule && - (cyclesProvider.cyclesIssueState == - StateEnum.loading || - cyclesProvider.cyclesDetailState == - StateEnum - .loading))) || - issueProvider.projectViewState == - StateEnum.loading - ? Center( - child: SizedBox( - width: 30, - height: 30, - child: LoadingIndicator( - indicatorType: Indicator - .lineSpinFadeLoader, - colors: [ - themeProvider.themeManager - .primaryTextColor - ], - strokeWidth: 1.0, - backgroundColor: themeProvider - .themeManager - .primaryBackgroundDefaultColor, - )), - ) - : ((!widget.fromModule && cyclesProvider.isIssuesEmpty) || - (widget.fromModule && - modulesProvider - .isIssuesEmpty)) - ? EmptyPlaceholder.emptyIssues(context, - cycleId: widget.cycleId, - moduleId: widget.moduleId, - projectId: widget.projId, - type: IssueCategory.cycleIssues, - ref: ref) - : ((!widget.fromModule && issueProvider.issues.projectView == IssueLayout.list) || - (widget.fromModule && - issueProvider.issues.projectView == - IssueLayout.list)) - ? Container( - color: themeProvider - .themeManager - .secondaryBackgroundDefaultColor, - margin: const EdgeInsets.only( - top: 5), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: (widget - .fromModule - ? modulesProvider - .issues - .issues - : cyclesProvider - .issues - .issues) - .map((state) => state - .items - .isEmpty && - (widget - .fromModule - ? !modulesProvider - .showEmptyStates - : !cyclesProvider - .showEmptyStates) - ? Container() - : SizedBox( - child: - Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - Container( - padding: const EdgeInsets - .only( - left: 15), - margin: const EdgeInsets - .only( - bottom: 10), - child: - Row( - children: [ - state.leading ?? Container(), - Container( - padding: const EdgeInsets.only( - left: 10, - ), - width: MediaQuery.of(context).size.width * 0.6, - child: CustomText( - state.title!, - overflow: TextOverflow.ellipsis, - maxLines: 1, - type: FontStyle.Small, - fontWeight: FontWeightt.Medium, - ), - ), - Container( - alignment: Alignment.center, - margin: const EdgeInsets.only( - left: 15, - ), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(15), color: themeProvider.themeManager.secondaryBackgroundDefaultColor), - height: 25, - width: 30, - child: CustomText( - state.items.length.toString(), - type: FontStyle.Medium, - ), - ), - const Spacer(), - IconButton( - onPressed: () { - if (issueProvider.issues.groupBY == GroupBY.state) { - issueProvider.createIssuedata['state'] = state.id; - } else { - issueProvider.createIssuedata['priority'] = 'de3c90cd-25cd-42ec-ac6c-a66caf8029bc'; - } - Navigator.of(context).push(MaterialPageRoute( - builder: (ctx) => CreateIssue( - moduleId: widget.moduleId, - cycleId: widget.cycleId, - ))); - }, - icon: Icon( - Icons.add, - color: themeProvider.themeManager.primaryColour, - )), - const SizedBox( - width: 10, - ), - ], - ), - ), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: state.items.map((e) => e).toList()), - state.items.isEmpty - ? Container( - margin: const EdgeInsets.only(bottom: 10), - width: MediaQuery.of(context).size.width, - color: themeProvider.themeManager.primaryBackgroundDefaultColor, - padding: const EdgeInsets.only(top: 15, bottom: 15, left: 15), - child: const CustomText( - 'No issues.', - type: FontStyle.Small, - maxLines: 10, - textAlign: TextAlign.start, - ), - ) - : Container( - margin: const EdgeInsets.only(bottom: 10), - ) - ], - ), - )) - .toList()), - ), - ) - : ((!widget.fromModule && issueProvider.issues.projectView == IssueLayout.kanban) || - (widget.fromModule && - issueProvider.issues.projectView == - IssueLayout.kanban)) - ? Padding( - padding: - const EdgeInsets.only( - left: 8), - child: KanbanBoard( - widget.fromModule - ? modulesProvider - .initializeBoard() - : cyclesProvider - .initializeBoard(), - boardID: - widget.fromModule - ? 'module-board' - : 'cycle-board', - onItemReorder: ( - {newCardIndex, - newListIndex, - oldCardIndex, - oldListIndex}) { - if (widget - .fromModule) { - modulesProvider - .reorderIssue( - newCardIndex: - newCardIndex!, - newListIndex: - newListIndex!, - oldCardIndex: - oldCardIndex!, - oldListIndex: - oldListIndex!, - ) - .catchError( - (err) { - CustomToast.showToast( - context, - message: - 'Failed to update issue', - toastType: - ToastType - .failure); - }); - } else { - cyclesProvider - .reorderIssue( - newCardIndex: - newCardIndex!, - newListIndex: - newListIndex!, - oldCardIndex: - oldCardIndex!, - oldListIndex: - oldListIndex!, - ) - .catchError( - (err) { - log(err - .toString()); - CustomToast.showToast( - context, - message: - 'Failed to update issue', - toastType: - ToastType - .failure); - }); - } - }, - isCardsDraggable: - issueProvider - .checkIsCardsDaraggable(), - groupEmptyStates: !(widget - .fromModule - ? modulesProvider - .showEmptyStates - : issueProvider - .showEmptyStates), - cardPlaceHolderColor: - themeProvider - .themeManager - .primaryBackgroundDefaultColor, - cardPlaceHolderDecoration: - BoxDecoration( - color: themeProvider - .themeManager - .primaryBackgroundDefaultColor, - boxShadow: [ - BoxShadow( - blurRadius: 2, - color: themeProvider - .themeManager - .borderSubtle01Color, - spreadRadius: 0, - ) - ]), - backgroundColor: - themeProvider - .themeManager - .secondaryBackgroundDefaultColor, - listScrollConfig: ScrollConfig( - offset: 65, - duration: - const Duration( - milliseconds: - 100), - curve: - Curves.linear), - listTransitionDuration: - const Duration( - milliseconds: - 200), - cardTransitionDuration: - const Duration( - milliseconds: - 400), - textStyle: TextStyle( - fontSize: 19, - height: 1.3, - color: Colors - .grey.shade800, - fontWeight: - FontWeight - .w500), - ), - ) - : ((!widget.fromModule && issueProvider.issues.projectView == IssueLayout.calendar) || (widget.fromModule && issueProvider.issues.projectView == IssueLayout.calendar)) - ? const CalendarView() - : SpreadSheetView( - issueCategory: - widget.fromModule - ? IssueCategory - .moduleIssues - : IssueCategory - .cycleIssues, - ), - ), - SafeArea( - child: Container( - height: 50, - width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - color: themeProvider.themeManager - .primaryBackgroundDefaultColor, - boxShadow: themeProvider.themeManager - .shadowBottomControlButtons), - child: Row( - children: [ - projectProvider.role == Role.admin || - projectProvider.role == Role.member - ? Expanded( - child: GestureDetector( - onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => - CreateIssue( - projectId: widget - .projId ?? - projectProvider - .currentProject[ - 'id'], - fromMyIssues: true, - moduleId: widget.moduleId, - cycleId: widget.cycleId, - ), - ), - ); - }, - child: SizedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Icon( - Icons.add, - color: themeProvider - .themeManager - .primaryTextColor, - size: 20, - ), - const CustomText( - ' Issue', - type: FontStyle.Medium, - ) - ], - ), - ), - ), - ) - : Container(), - Container( - height: 50, - width: 0.5, - color: themeProvider - .themeManager.borderSubtle01Color, - ), - Expanded( - child: GestureDetector( - onTap: () { - showModalBottomSheet( - isScrollControlled: true, - enableDrag: true, - constraints: BoxConstraints( - maxHeight: - MediaQuery.of(context) - .size - .height * - 0.85), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(30), - topRight: Radius.circular(30), - )), - context: context, - builder: (ctx) { - return TypeSheet( - issueCategory: widget.fromModule - ? IssueCategory.moduleIssues - : IssueCategory.cycleIssues, - ); - }); - }, - child: SizedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Icon( - Icons.menu, - color: themeProvider.themeManager - .primaryTextColor, - size: 19, - ), - const CustomText( - ' Layout', - type: FontStyle.Medium, - ) - ], - ), - ), - )), - Container( - height: 50, - width: 0.5, - color: themeProvider - .themeManager.borderSubtle01Color, - ), - issueProvider.issues.projectView == - IssueLayout.calendar - ? Container() - : Expanded( - child: GestureDetector( - onTap: () { - showModalBottomSheet( - isScrollControlled: true, - enableDrag: true, - constraints: BoxConstraints( - maxHeight: - MediaQuery.of(context) - .size - .height * - 0.9), - shape: - const RoundedRectangleBorder( - borderRadius: - BorderRadius.only( - topLeft: - Radius.circular(30), - topRight: - Radius.circular(30), - )), - context: context, - builder: (ctx) { - return ViewsSheet( - projectView: issueProvider - .issues.projectView, - issueCategory: - widget.fromModule - ? IssueCategory - .moduleIssues - : IssueCategory - .cycleIssues, - cycleId: widget.cycleId, - ); - }); - }, - child: SizedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Icon( - Icons.wysiwyg_outlined, - color: themeProvider - .themeManager - .primaryTextColor, - size: 19, - ), - const CustomText( - ' Display', - type: FontStyle.Medium, - ) - ], - ), - ), - )), - Container( - height: 50, - width: 0.5, - color: themeProvider - .themeManager.borderSubtle01Color, - ), - Expanded( - child: GestureDetector( - onTap: () { - showModalBottomSheet( - isScrollControlled: true, - enableDrag: true, - constraints: BoxConstraints( - maxHeight: - MediaQuery.of(context) - .size - .height * - 0.85), - shape: - const RoundedRectangleBorder( - borderRadius: - BorderRadius.only( - topLeft: Radius.circular(30), - topRight: Radius.circular(30), - )), - context: context, - builder: (ctx) { - return FilterSheet( - issueCategory: - widget.fromModule - ? IssueCategory - .moduleIssues - : IssueCategory - .cycleIssues, - cycleOrModuleId: - widget.fromModule - ? widget.moduleId - : widget.cycleId, - ); - }); - }, - child: SizedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Icon( - Icons.filter_list_outlined, - color: themeProvider - .themeManager - .primaryTextColor, - size: 19, - ), - const CustomText( - ' Filters', - type: FontStyle.Medium, - ) - ], - ), - ), - ), - ), - ], - ), - ), - ), - ], - ), - // Container( - // color: themeProvider - // .themeManager.secondaryBackgroundDefaultColor, - // padding: const EdgeInsets.only(left: 25, right: 25), - // child: activeCycleDetails( - // fromModule: widget.fromModule ? true : false), - // ), - ], - ), - ), - ], - ), - ), - ); - } - - Widget activeCycleDetails({bool fromModule = false}) { - final themeProvider = ref.watch(ProviderList.themeProvider); - final cyclesProvider = ref.watch(ProviderList.cyclesProvider); - final modulesProvider = ref.watch(ProviderList.modulesProvider); - - if (modulesProvider.moduleDetailState == StateEnum.loading || - cyclesProvider.cyclesDetailState == StateEnum.loading) { - return Center( - child: SizedBox( - width: 30, - height: 30, - child: LoadingIndicator( - indicatorType: Indicator.lineSpinFadeLoader, - colors: [themeProvider.themeManager.primaryTextColor], - strokeWidth: 1.0, - backgroundColor: Colors.transparent, - ), - ), - ); - } else { - return ListView( - children: [ - const SizedBox(height: 30), - datePart(), - const SizedBox(height: 30), - detailsPart(), - const SizedBox(height: 30), - progressPart(), - const SizedBox(height: 30), - assigneesPart(fromModule: widget.fromModule), - const SizedBox(height: 30), - statesPart(), - const SizedBox(height: 30), - labelsPart(fromModule: widget.fromModule), - const SizedBox(height: 30), - // widget.fromModule ? links() : Container() - ], - ); - } - } - - Widget links() { - final themeProvider = ref.watch(ProviderList.themeProvider); - final ModuleProvider moduleProvider = - ref.watch(ProviderList.modulesProvider); - return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - CustomText( - 'Links', - type: FontStyle.Medium, - fontWeight: FontWeightt.Medium, - color: themeProvider.themeManager.primaryTextColor, - ), - GestureDetector( - onTap: () { - showModalBottomSheet( - isScrollControlled: true, - enableDrag: true, - constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.85), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(30), - topRight: Radius.circular(30), - )), - context: context, - builder: (ctx) { - return SingleChildScrollView( - child: Padding( - padding: EdgeInsets.only( - bottom: MediaQuery.of(context).viewInsets.bottom), - child: const AddLinkSheet(), - ), - ); - }, - ); - }, - child: Icon( - Icons.add, - color: themeProvider.themeManager.primaryTextColor, - )) - ], - ), - const SizedBox(height: 10), - moduleProvider.moduleDetailsData['link_module'].isNotEmpty - ? Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - decoration: BoxDecoration( - color: themeProvider.themeManager.primaryBackgroundDefaultColor, - borderRadius: BorderRadius.circular(5), - border: Border.all( - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: ListView.builder( - shrinkWrap: true, - itemCount: - moduleProvider.moduleDetailsData['link_module'].length, - itemBuilder: (ctx, index) { - return SizedBox( - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - margin: const EdgeInsets.only(top: 5), - child: Transform.rotate( - angle: -20, - child: Icon( - Icons.link, - color: - themeProvider.themeManager.primaryTextColor, - size: 20, - ), - ), - ), - const SizedBox( - width: 10, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - moduleProvider.moduleDetailsData['link_module'] - [index]['title'] != - null - ? CustomText( - moduleProvider - .moduleDetailsData['link_module'] - [index]['title'] - .toString(), - type: FontStyle.Medium, - ) - : Container(), - CustomText( - 'by ${moduleProvider.moduleDetailsData['link_module'][index]['created_by_detail']['display_name']}', - type: FontStyle.Small, - color: themeProvider - .themeManager.placeholderTextColor, - ) - ], - ), - const Spacer(), - GestureDetector( - onTap: () { - showModalBottomSheet( - isScrollControlled: true, - enableDrag: true, - constraints: BoxConstraints( - maxHeight: - MediaQuery.of(context).size.height * - 0.85), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(30), - topRight: Radius.circular(30), - )), - context: context, - builder: (ctx) { - return SingleChildScrollView( - child: Padding( - padding: EdgeInsets.only( - bottom: MediaQuery.of(context) - .viewInsets - .bottom), - child: AddLinkSheet( - id: moduleProvider.moduleDetailsData[ - 'link_module'][index]['id'], - ), - ), - ); - }, - ); - }, - child: Icon( - Icons.edit_outlined, - color: themeProvider - .themeManager.placeholderTextColor, - size: 20, - ), - ), - const SizedBox( - width: 10, - ), - GestureDetector( - onTap: () { - moduleProvider.handleLinks( - linkID: moduleProvider - .moduleDetailsData['link_module'] - [index]['id'], - data: {}, - method: HttpMethod.delete, - context: context); - }, - child: Icon( - Icons.delete_outline, - color: themeProvider - .themeManager.placeholderTextColor, - size: 20, - ), - ), - ], - ), - ); - }), - ) - : Container() - ]); - } - - Widget datePart() { - final cyclesProvider = ref.watch(ProviderList.cyclesProvider); - final modulesProvider = ref.watch(ProviderList.modulesProvider); - final themeProvider = ref.watch(ProviderList.themeProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); - final detailData = widget.fromModule - ? modulesProvider.moduleDetailsData - : cyclesProvider.cyclesDetailsData; - - startDate = DateFormat('yyyy-MM-dd').parse( - detailData['start_date'] == null || detailData['start_date'] == '' - ? DateTime.now().toString() - : detailData['start_date']!); - - dueDate = DateFormat('yyyy-MM-dd').parse( - detailData[widget.fromModule ? 'target_date' : 'end_date'] == null || - detailData[widget.fromModule ? 'target_date' : 'end_date'] == '' - ? DateTime.now().toString() - : detailData[widget.fromModule ? 'target_date' : 'end_date']!); - - return Wrap( - runSpacing: 20, - children: [ - (detailData['start_date'] == null || detailData['start_date'] == '') || - (detailData[widget.fromModule ? 'target_date' : 'end_date'] == - null || - detailData[ - widget.fromModule ? 'target_date' : 'end_date'] == - '') - ? Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - border: Border.all( - width: 1, - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: const CustomText( - 'Draft', - type: FontStyle.Small, - ), - ) - : Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: checkDate( - startDate: detailData['start_date'], - endDate: detailData[widget.fromModule - ? 'target_date' - : 'end_date']) == - 'Draft' - ? themeProvider - .themeManager.tertiaryBackgroundDefaultColor - : checkDate( - startDate: detailData['start_date'], - endDate: detailData[widget.fromModule - ? 'target_date' - : 'end_date']) == - 'Completed' - ? themeProvider - .themeManager.secondaryBackgroundActiveColor - : themeProvider.themeManager.successBackgroundColor, - borderRadius: BorderRadius.circular(5)), - child: CustomText( - checkDate( - startDate: detailData['start_date'], - endDate: detailData[ - widget.fromModule ? 'target_date' : 'end_date'], - ), - type: FontStyle.Small, - color: checkDate( - startDate: detailData['start_date'], - endDate: detailData[ - widget.fromModule ? 'target_date' : 'end_date'], - ) == - 'Draft' - ? greyColor - : checkDate( - startDate: detailData['start_date'], - endDate: detailData[widget.fromModule - ? 'target_date' - : 'end_date'], - ) == - 'Completed' - ? themeProvider.themeManager.primaryColour - : greenHighLight, - ), - ), - const SizedBox(width: 20), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - GestureDetector( - onTap: () async { - if (projectProvider.role != Role.admin && - projectProvider.role != Role.member) { - CustomToast.showToast(context, - message: accessRestrictedMSG, - toastType: ToastType.failure); - return; - } - final date = await showDatePicker( - builder: (context, child) => Theme( - data: themeProvider.themeManager.datePickerThemeData, - child: child!, - ), - context: context, - initialDate: startDate!, - firstDate: DateTime(2020), - lastDate: DateTime(2025), - ); - if (date != null) { - final bool dateNotConflicted = dueDate == null - ? true - : widget.fromModule - ? true - : await cyclesProvider.dateCheck( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: ref - .read(ProviderList.projectProvider) - .currentProject["id"], - data: { - "cycle_id": widget.cycleId!, - "start_date": - DateFormat('yyyy-MM-dd').format(date), - "end_date": - DateFormat('yyyy-MM-dd').format(dueDate!), - }, - ); - if (dateNotConflicted) { - if (dueDate != null && date.isAfter(dueDate!)) { - CustomToast.showToast(context, - message: 'Start date cannot be after end date', - toastType: ToastType.failure); - return; - } - setState(() { - startDate = date; - }); - } else { - CustomToast.showToast(context, - message: 'Date is conflicted with other cycle', - toastType: ToastType.failure); - return; - } - } - - if (date != null) { - if (widget.fromModule) { - modulesProvider.updateModules( - disableLoading: true, - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projId: ref - .read(ProviderList.projectProvider) - .currentProject["id"], - moduleId: widget.moduleId!, - data: { - 'start_date': DateFormat('yyyy-MM-dd').format(date) - }, - ref: ref); - } else { - cyclesProvider.cycleDetailsCrud( - disableLoading: true, - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: ref - .read(ProviderList.projectProvider) - .currentProject["id"], - method: CRUD.update, - cycleId: widget.cycleId!, - data: { - 'start_date': DateFormat('yyyy-MM-dd').format(date) - }, - ); - } - } - }, - child: Container( - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: - themeProvider.themeManager.primaryBackgroundDefaultColor, - border: Border.all( - width: 1, - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: (detailData['start_date'] == null || - detailData['start_date'] == '') || - (detailData[widget.fromModule - ? 'target_date' - : 'end_date'] == - null || - detailData[widget.fromModule - ? 'target_date' - : 'end_date'] == - '') - ? CustomText( - 'Start Date', - type: FontStyle.Small, - fontWeight: FontWeightt.Regular, - color: themeProvider.themeManager.secondaryTextColor, - ) - : Row( - children: [ - Icon(Icons.calendar_today_outlined, - size: 15, - color: themeProvider - .themeManager.placeholderTextColor), - const SizedBox(width: 7), - CustomText( - '${dateFormating(detailData['start_date'])} ', - type: FontStyle.Small, - fontWeight: FontWeightt.Regular, - color: - themeProvider.themeManager.secondaryTextColor, - ), - ], - ), - ), - ), - //arrow - const SizedBox(width: 5), - Icon( - Icons.arrow_forward, - size: 15, - color: themeProvider.themeManager.placeholderTextColor, - ), - const SizedBox(width: 5), - GestureDetector( - onTap: () async { - if (projectProvider.role != Role.admin && - projectProvider.role != Role.member) { - CustomToast.showToast(context, - message: accessRestrictedMSG, - toastType: ToastType.failure); - return; - } - final date = await showDatePicker( - builder: (context, child) => Theme( - data: themeProvider.themeManager.datePickerThemeData, - child: child!, - ), - context: context, - initialDate: dueDate!, - firstDate: startDate ?? DateTime.now(), - lastDate: DateTime(2025), - ); - - if (date != null) { - if (!date.isAfter(DateTime.now())) { - CustomToast.showToast(context, - message: 'Due date not valid ', - toastType: ToastType.failure); - return; - } - if (date.isAfter(startDate!)) { - final bool dateNotConflicted = widget.fromModule - ? true - : await cyclesProvider.dateCheck( - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: ref - .read(ProviderList.projectProvider) - .currentProject["id"], - data: { - "cycle_id": widget.cycleId!, - "start_date": - DateFormat('yyyy-MM-dd').format(startDate!), - "end_date": DateFormat('yyyy-MM-dd').format(date), - }, - ); - - if (dateNotConflicted) { - setState(() { - dueDate = date; - }); - if (widget.fromModule) { - modulesProvider.updateModules( - disableLoading: true, - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projId: ref - .read(ProviderList.projectProvider) - .currentProject["id"], - moduleId: widget.moduleId!, - data: { - 'target_date': - DateFormat('yyyy-MM-dd').format(date) - }, - ref: ref); - modulesProvider.changeTabIndex(1); - } else { - cyclesProvider.cycleDetailsCrud( - disableLoading: true, - slug: ref - .read(ProviderList.workspaceProvider) - .selectedWorkspace - .workspaceSlug, - projectId: ref - .read(ProviderList.projectProvider) - .currentProject["id"], - method: CRUD.update, - cycleId: widget.cycleId!, - data: { - 'end_date': DateFormat('yyyy-MM-dd').format(date) - }, - ); - cyclesProvider.changeTabIndex(1); - } - } else { - CustomToast.showToast(context, - message: 'Date is conflicted with other cycle ', - toastType: ToastType.failure); - } - } else { - CustomToast.showToast(context, - message: 'Start date cannot be after end date ', - toastType: ToastType.failure); - } - } - }, - child: Container( - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: - themeProvider.themeManager.primaryBackgroundDefaultColor, - border: Border.all( - width: 1, - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: (detailData['start_date'] == null || - detailData['start_date'] == '') || - (detailData[widget.fromModule - ? 'target_date' - : 'end_date'] == - null || - detailData[widget.fromModule - ? 'target_date' - : 'end_date'] == - '') - ? CustomText('End Date', - type: FontStyle.Small, - fontWeight: FontWeightt.Regular, - color: themeProvider.themeManager.secondaryTextColor) - : Row( - children: [ - Icon(Icons.calendar_today_outlined, - size: 15, - color: themeProvider - .themeManager.placeholderTextColor), - const SizedBox(width: 5), - CustomText( - '${dateFormating(detailData[widget.fromModule ? 'target_date' : 'end_date'])} ', - type: FontStyle.Small, - fontWeight: FontWeightt.Regular, - color: themeProvider - .themeManager.secondaryTextColor), - ], - ), - ), - ), - ], - ), - ], - ); - } - - Widget detailsPart() { - final themeProvider = ref.watch(ProviderList.themeProvider); - return Column( - children: [ - Align( - alignment: Alignment.centerLeft, - child: CustomText( - 'Details', - type: FontStyle.Medium, - fontWeight: FontWeightt.Medium, - color: themeProvider.themeManager.primaryTextColor, - )), - const SizedBox(height: 10), - stateWidget(), - const SizedBox(height: 10), - assigneeWidget(), - widget.fromModule - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 10), - membersWidget(), - ], - ) - : Container(), - ], - ); - } - - Widget progressPart() { - final themeProvider = ref.watch(ProviderList.themeProvider); - return Column( - children: [ - Align( - alignment: Alignment.centerLeft, - child: CustomText( - 'Progress', - type: FontStyle.Medium, - fontWeight: FontWeightt.Medium, - color: themeProvider.themeManager.primaryTextColor, - )), - const SizedBox(height: 10), - Container( - padding: - const EdgeInsets.only(left: 20, right: 30, top: 35, bottom: 20), - decoration: BoxDecoration( - color: themeProvider.themeManager.primaryBackgroundDefaultColor, - borderRadius: BorderRadius.circular(5), - border: Border.all( - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: SizedBox( - height: 200, - child: SfCartesianChart( - plotAreaBorderColor: Colors.transparent, - margin: EdgeInsets.zero, - primaryYAxis: NumericAxis( - majorGridLines: - const MajorGridLines(width: 0), // Remove major grid lines - ), - primaryXAxis: CategoryAxis( - labelPlacement: - LabelPlacement.betweenTicks, // Adjust label placement - interval: chartData.length > 5 ? 3 : 1, - majorGridLines: const MajorGridLines( - width: 0, - ), // Remove major grid lines - minorGridLines: const MinorGridLines(width: 0), - axisLabelFormatter: (axisLabelRenderArgs) { - return ChartAxisLabel( - DateFormat('dd MMM') - .format(DateTime.parse(axisLabelRenderArgs.text)), - const TextStyle(fontWeight: FontWeight.normal)); - }, - ), - series: [ - // Renders area chart - AreaSeries( - gradient: LinearGradient( - begin: Alignment.bottomCenter, - end: Alignment.topCenter, - colors: [ - Colors.transparent, - themeProvider.themeManager.primaryColour - .withOpacity(0.2), - themeProvider.themeManager.primaryColour - .withOpacity(0.3), - ]), - dataSource: chartData, - xValueMapper: (ChartData data, _) => data.x, - yValueMapper: (ChartData data, _) => data.y, - ), - LineSeries( - dashArray: [5.0, 5.0], - dataSource: chartData.isNotEmpty - ? [ - ChartData(chartData.first.x, - chartData.first.y), // First data point - ChartData(chartData.last.x, - 0.0), // Data point at current time with Y-value of last data point - ] - : [], - xValueMapper: (ChartData data, _) => data.x, - yValueMapper: (ChartData data, _) => data.y, - ), - ], - ), - ), - ), - ], - ); - } - - Widget assigneesPart({bool fromModule = false}) { - final cyclesProvider = ref.watch(ProviderList.cyclesProvider); - final modulesProvider = ref.watch(ProviderList.modulesProvider); - final issuesProvider = ref.watch(ProviderList.issuesProvider); - final themeProvider = ref.watch(ProviderList.themeProvider); - - final detailData = widget.fromModule - ? modulesProvider.moduleDetailsData - : cyclesProvider.cyclesDetailsData; - - return Column( - children: [ - Align( - alignment: Alignment.centerLeft, - child: CustomText( - 'Assignees', - type: FontStyle.Medium, - fontWeight: FontWeightt.Medium, - color: themeProvider.themeManager.primaryTextColor, - )), - const SizedBox(height: 10), - detailData['assignees'].length == 0 - ? const CustomText('No data found.') - : Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - decoration: BoxDecoration( - color: - themeProvider.themeManager.primaryBackgroundDefaultColor, - borderRadius: BorderRadius.circular(5), - border: Border.all( - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: Column( - children: [ - ...List.generate( - detailData['assignees'].length, - (idx) { - return Container( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 8), - margin: const EdgeInsets.symmetric(vertical: 2), - decoration: BoxDecoration( - color: (issuesProvider.issues.filters.assignees - .contains(detailData['assignees'][idx] - ['assignee_id']) - ? themeProvider.themeManager - .secondaryBackgroundDefaultColor - : themeProvider.themeManager - .primaryBackgroundDefaultColor), - borderRadius: BorderRadius.circular(5), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Padding( - padding: const EdgeInsets.only(right: 10), - child: detailData['assignees'][idx] - ['avatar'] != - null && - detailData['assignees'][idx] - ['avatar'] != - '' - ? CircleAvatar( - radius: 10, - backgroundImage: NetworkImage( - detailData['assignees'][idx] - ['avatar']), - ) - : CircleAvatar( - radius: 10, - backgroundColor: themeProvider - .themeManager - .tertiaryBackgroundDefaultColor, - child: Center( - child: CustomText( - detailData['assignees'][idx] - ['first_name'] != - null - ? detailData['assignees'] - [idx] - ['first_name'][0] - .toString() - .toUpperCase() - : '', - type: FontStyle.Small, - ), - ), - )), - CustomText( - detailData['assignees'][idx] - ['display_name'] ?? - 'No Assignees', - color: themeProvider - .themeManager.secondaryTextColor, - ), - ], - ), - CompletionPercentage( - value: detailData['assignees'][idx] - ['completed_issues'], - totalValue: detailData['assignees'][idx] - ['total_issues']) - ], - ), - ); - }, - ), - ], - ), - ), - ], - ); - } - - Widget statesPart() { - final List states = [ - "Backlog", - "Unstarted", - "Started", - "Cancelled", - "Completed", - ]; - final cyclesProvider = ref.watch(ProviderList.cyclesProvider); - final modulesProvider = ref.watch(ProviderList.modulesProvider); - final themeProvider = ref.watch(ProviderList.themeProvider); - - final detailData = widget.fromModule - ? modulesProvider.moduleDetailsData - : cyclesProvider.cyclesDetailsData; - - return Column( - children: [ - Align( - alignment: Alignment.centerLeft, - child: CustomText( - 'States', - type: FontStyle.Medium, - fontWeight: FontWeightt.Medium, - color: themeProvider.themeManager.primaryTextColor, - )), - const SizedBox(height: 10), - Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - decoration: BoxDecoration( - color: themeProvider.themeManager.primaryBackgroundDefaultColor, - borderRadius: BorderRadius.circular(5), - border: Border.all( - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: Column( - children: [ - ...List.generate( - states.length, - (index) => Row( - children: [ - const SizedBox(height: 50), - Padding( - padding: const EdgeInsets.only(right: 10), - child: SvgPicture.asset( - states[index] == 'Backlog' - ? 'assets/svg_images/circle.svg' - : states[index] == 'Unstarted' - ? 'assets/svg_images/in_progress.svg' - : states[index] == 'Started' - ? 'assets/svg_images/done.svg' - : states[index] == 'Cancelled' - ? 'assets/svg_images/cancelled.svg' - : 'assets/svg_images/circle.svg', - height: 22, - width: 22, - colorFilter: ColorFilter.mode( - index == 0 - ? const Color(0xFFCED4DA) - : index == 1 - ? const Color(0xFF26B5CE) - : index == 2 - ? const Color(0xFFF7AE59) - : index == 3 - ? const Color(0xFFD687FF) - : greenHighLight, - BlendMode.srcIn)), - ), - CustomText( - states[index], - type: FontStyle.Large, - fontWeight: FontWeightt.Regular, - color: themeProvider.themeManager.secondaryTextColor, - ), - const Spacer(), - index == 0 - ? CompletionPercentage( - value: detailData['backlog_issues'], - totalValue: detailData['total_issues']) - : index == 1 - ? CompletionPercentage( - value: detailData['unstarted_issues'], - totalValue: detailData['total_issues']) - : index == 2 - ? CompletionPercentage( - value: detailData['started_issues'], - totalValue: detailData['total_issues']) - : index == 3 - ? CompletionPercentage( - value: detailData['cancelled_issues'], - totalValue: detailData['total_issues']) - : CompletionPercentage( - value: detailData['completed_issues'], - totalValue: detailData['total_issues'], - ), - ], - ), - ), - ], - ), - ), - ], - ); - } - - Widget labelsPart({bool fromModule = false}) { - final cyclesProvider = ref.watch(ProviderList.cyclesProvider); - final issuesProvider = ref.watch(ProviderList.issuesProvider); - final modulesProvider = ref.watch(ProviderList.modulesProvider); - final themeProvider = ref.watch(ProviderList.themeProvider); - - final detailData = widget.fromModule - ? modulesProvider.moduleDetailsData - : cyclesProvider.cyclesDetailsData; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Align( - alignment: Alignment.centerLeft, - child: CustomText( - 'Labels', - type: FontStyle.Medium, - fontWeight: FontWeightt.Medium, - color: themeProvider.themeManager.primaryTextColor, - )), - const SizedBox(height: 10), - detailData['distribution']['labels'].isNotEmpty - ? Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), - decoration: BoxDecoration( - color: - themeProvider.themeManager.primaryBackgroundDefaultColor, - borderRadius: BorderRadius.circular(5), - border: Border.all( - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: ListView.builder( - shrinkWrap: true, - primary: false, - itemCount: detailData['distribution']['labels'].length, - itemBuilder: (context, index) { - return Container( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 8), - margin: const EdgeInsets.symmetric(vertical: 2), - decoration: BoxDecoration( - color: issuesProvider.issues.filters.labels.contains( - detailData['distribution']['labels'][index] - ['label_id']) - ? themeProvider - .themeManager.secondaryBackgroundDefaultColor - : themeProvider - .themeManager.primaryBackgroundDefaultColor, - borderRadius: BorderRadius.circular(5), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Icon( - Icons.circle, - size: 20, - color: detailData['distribution']['labels'] - [index]['label_name'] == - null - ? themeProvider.themeManager - .tertiaryBackgroundDefaultColor - : detailData['distribution']['labels'] - [index]['color'] == - '' || - detailData['distribution'] - ['labels'][index] - ['color'] == - null - ? themeProvider - .themeManager.placeholderTextColor - : detailData['distribution']['labels'] - [index]['color'] - .toString() - .toColor(), - ), - const SizedBox( - width: 10, - ), - SizedBox( - width: width * 0.4, - child: CustomText( - detailData['distribution']['labels'][index] - ['label_name'] ?? - 'No Label', - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - Row( - children: [ - CompletionPercentage( - value: detailData['distribution']['labels'] - [index]['completed_issues'], - totalValue: detailData['distribution'] - ['labels'][index]['total_issues']) - ], - ) - ], - ), - ); - }), - ) - : const Align( - alignment: Alignment.center, - child: CustomText('No data found'), - ) - ], - ); - } - - Widget stateWidget({bool fromModule = false}) { - final cyclesProvider = ref.watch(ProviderList.cyclesProvider); - final modulesProvider = ref.watch(ProviderList.modulesProvider); - final themeProvider = ref.watch(ProviderList.themeProvider); - return Container( - height: 45, - width: double.infinity, - decoration: BoxDecoration( - color: themeProvider.themeManager.primaryBackgroundDefaultColor, - borderRadius: BorderRadius.circular(5), - border: Border.all( - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: Padding( - padding: const EdgeInsets.only(left: 10, right: 10), - child: Row( - children: [ - //icon - Icon( - //four squares icon - Icons.timelapse_rounded, - color: themeProvider.themeManager.placeholderTextColor), - const SizedBox(width: 15), - CustomText( - 'Progress', - type: FontStyle.Medium, - fontWeight: FontWeightt.Regular, - color: themeProvider.themeManager.placeholderTextColor, - ), - Expanded(child: Container()), - - CompletionPercentage( - value: widget.fromModule - ? modulesProvider.moduleDetailsData['completed_issues'] - : cyclesProvider.cyclesDetailsData['completed_issues'], - totalValue: widget.fromModule - ? modulesProvider.moduleDetailsData['total_issues'] - : cyclesProvider.cyclesDetailsData['total_issues']) - ], - ), - ), - ); - } - - Widget membersWidget() { - final modulesProvider = ref.watch(ProviderList.modulesProvider); - final themeProvider = ref.watch(ProviderList.themeProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); - return GestureDetector( - onTap: () { - if (projectProvider.role != Role.admin && - projectProvider.role != Role.member) { - CustomToast.showToast(context, - message: accessRestrictedMSG, toastType: ToastType.failure); - return; - } - showModalBottomSheet( - constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.5, - ), - isScrollControlled: true, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20), - ), - ), - context: context, - builder: (context) => AssigneeSheet( - fromModuleDetail: widget.fromModule, - ), - ); - }, - child: Container( - height: 45, - width: double.infinity, - decoration: BoxDecoration( - color: themeProvider.themeManager.primaryBackgroundDefaultColor, - borderRadius: BorderRadius.circular(5), - border: Border.all( - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: Padding( - padding: const EdgeInsets.only(left: 10, right: 10), - child: Row( - children: [ - //icon - Icon( - //two people icon - Icons.people_alt_rounded, - color: themeProvider.themeManager.placeholderTextColor, - ), - const SizedBox(width: 15), - CustomText( - 'Members', - type: FontStyle.Medium, - fontWeight: FontWeightt.Regular, - color: themeProvider.themeManager.placeholderTextColor, - ), - Expanded(child: Container()), - (modulesProvider.currentModule['members_detail'] == null || - modulesProvider.currentModule['members_detail'].isEmpty) - ? Row( - children: [ - CustomText( - 'No members', - type: FontStyle.Medium, - fontWeight: FontWeightt.Regular, - color: themeProvider.themeManager.primaryTextColor, - ), - const SizedBox( - width: 5, - ), - Icon( - Icons.keyboard_arrow_down, - color: themeProvider.themeManager.primaryTextColor, - ), - ], - ) - : SizedBox( - height: 27, - child: FittedBox( - fit: BoxFit.scaleDown, - alignment: Alignment.center, - child: SizedBox( - height: 30, - child: SquareAvatarWidget( - borderRadius: 50, - details: modulesProvider - .currentModule['members_detail']), - ), - ), - ) - ], - ), - ), - ), - ); - } - - Widget assigneeWidget() { - final cyclesProvider = ref.watch(ProviderList.cyclesProvider); - final modulesProvider = ref.watch(ProviderList.modulesProvider); - final themeProvider = ref.watch(ProviderList.themeProvider); - final projectProvider = ref.watch(ProviderList.projectProvider); - final detailData = widget.fromModule - ? modulesProvider.moduleDetailsData - : cyclesProvider.cyclesDetailsData; - - return GestureDetector( - onTap: widget.fromModule - ? () { - if (projectProvider.role != Role.admin && - projectProvider.role != Role.member) { - CustomToast.showToast(context, - message: accessRestrictedMSG, toastType: ToastType.failure); - return; - } - showModalBottomSheet( - constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.5, - ), - isScrollControlled: true, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20), - ), - ), - context: context, - builder: (context) => LeadSheet( - fromModuleDetail: widget.fromModule, - ), - ); - } - : () {}, - child: Container( - height: 45, - width: double.infinity, - decoration: BoxDecoration( - color: themeProvider.themeManager.primaryBackgroundDefaultColor, - borderRadius: BorderRadius.circular(5), - border: Border.all( - color: themeProvider.themeManager.borderSubtle01Color, - ), - ), - child: Padding( - padding: const EdgeInsets.only(left: 10, right: 10), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - //icon - Icon( - //two people icon - Icons.people_outline_outlined, - color: themeProvider.themeManager.placeholderTextColor, - ), - const SizedBox(width: 15), - CustomText( - 'Lead', - type: FontStyle.Medium, - fontWeight: FontWeightt.Regular, - color: themeProvider.themeManager.placeholderTextColor, - ), - const Spacer(), - detailData[widget.fromModule ? 'lead_detail' : 'owned_by'] == null - ? CustomText( - 'No lead', - type: FontStyle.Medium, - fontWeight: FontWeightt.Regular, - color: themeProvider.themeManager.primaryTextColor, - ) - : Row( - children: [ - MemberLogoWidget( - fontType: FontStyle.Small, - boarderRadius: 50, - padding: EdgeInsets.zero, - size: 25, - imageUrl: (detailData[widget.fromModule - ? 'lead_detail' - : 'owned_by']['avatar']), - colorForErrorWidget: - const Color.fromRGBO(55, 65, 81, 1), - memberNameFirstLetterForErrorWidget: detailData[ - widget.fromModule - ? 'lead_detail' - : 'owned_by']['display_name'][0] - .toString()), - const SizedBox(width: 5), - Container( - constraints: BoxConstraints(maxWidth: width * 0.4), - child: CustomText( - (detailData[widget.fromModule - ? 'lead_detail' - : 'owned_by'] != - null && - detailData[widget.fromModule - ? 'lead_detail' - : 'owned_by']['display_name'] != - null) - ? detailData[widget.fromModule - ? 'lead_detail' - : 'owned_by']['display_name'] ?? - '' - : '', - type: FontStyle.Small, - maxLines: 1, - ), - ), - ], - ), - ], - ), - ), - ), - ); - } - - String dateFormating(String date) { - final DateTime formatedDate = DateTime.parse(date); - final String finalDate = DateFormat('dd MMM').format(formatedDate); - return finalDate; - } - - String checkDate({required String startDate, required String endDate}) { - final DateTime now = DateTime.now(); - if ((startDate.isEmpty) || (endDate.isEmpty)) { - return 'Draft'; - } else { - if (DateTime.parse(startDate).isAfter(now)) { - final Duration difference = - DateTime.parse(startDate.split('+').first).difference(now); - if (difference.inDays == 0) { - return 'Today'; - } else { - return '${difference.inDays.abs() + 1} Days Left'; - } - } - if (DateTime.parse(startDate).isBefore(now) && - DateTime.parse(endDate).isAfter(now)) { - final Duration difference = DateTime.parse(endDate).difference(now); - if (difference.inDays == 0) { - return 'Today'; - } else { - return '${difference.inDays.abs() + 1} Days Left'; - } - } else { - return 'Completed'; - } - } - } - - String checkTimeDifferenc(String dateTime) { - final DateTime now = DateTime.now(); - final Duration difference = now.difference(DateTime.parse(dateTime)); - String? format; - - if (difference.inDays > 0) { - format = '${difference.inDays} days ago'; - } else if (difference.inHours > 0) { - format = '${difference.inHours} hours ago'; - } else if (difference.inMinutes > 0) { - format = '${difference.inMinutes} minutes ago'; - } else { - format = '${difference.inSeconds} seconds ago'; - } - - return format; - } -} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart index 8e0f76d7..b015d7c9 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; @@ -33,7 +33,7 @@ class _ListLayoutRootState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - padding: const EdgeInsets.only(left: 15), + // padding: const EdgeInsets.only(left: 15), margin: const EdgeInsets.only(bottom: 10), child: Row( children: [ @@ -42,8 +42,6 @@ class _ListLayoutRootState extends ConsumerState { padding: const EdgeInsets.only( left: 10, ), - width: - MediaQuery.of(context).size.width * 0.6, child: CustomText( state.title!, overflow: TextOverflow.ellipsis, @@ -93,9 +91,6 @@ class _ListLayoutRootState extends ConsumerState { : Container( height: 40, ), - const SizedBox( - width: 10, - ), ], ), ), diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart index 5a9b6f1c..993434eb 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart @@ -19,7 +19,7 @@ import 'package:plane/config/const.dart'; import 'package:plane/mixins/widget_state_mixin.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/selected_label_widget.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/selected_label_widget.dart'; import 'package:plane/utils/color_manager.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/selected_label_widget.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/selected_label_widget.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/selected_label_widget.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/selected_label_widget.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Issues/issues_tab.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Issues/issues_tab.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_detail_page.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_detail_page.dart new file mode 100644 index 00000000..710d8783 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_detail_page.dart @@ -0,0 +1,663 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:intl/intl.dart'; +import 'package:loading_indicator/loading_indicator.dart'; +import 'package:plane/bottom_sheets/assignee_sheet.dart'; +import 'package:plane/models/chart_model.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/links_widget.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart'; +import 'package:plane/utils/constants.dart'; +import 'package:plane/utils/custom_toast.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/utils/extensions/string_extensions.dart'; +import 'package:plane/widgets/completion_percentage.dart'; +import 'package:plane/widgets/custom_text.dart'; +import 'package:plane/widgets/square_avatar_widget.dart'; + +class ModuleDetailsPage extends ConsumerStatefulWidget { + const ModuleDetailsPage( + {super.key, required this.moduleId, required this.chartData}); + final String moduleId; + final List chartData; + + @override + ConsumerState createState() => _ModuleDetailsPageState(); +} + +class _ModuleDetailsPageState extends ConsumerState { + DateTime? dueDate; + DateTime? startDate; + + @override + Widget build(BuildContext context) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final modulesProvider = ref.watch(ProviderList.modulesProvider); + + if (modulesProvider.moduleDetailState == StateEnum.loading) { + return Center( + child: SizedBox( + width: 30, + height: 30, + child: LoadingIndicator( + indicatorType: Indicator.lineSpinFadeLoader, + colors: [themeProvider.themeManager.primaryTextColor], + strokeWidth: 1.0, + backgroundColor: Colors.transparent, + ), + ), + ); + } else { + return ListView( + children: [ + const SizedBox(height: 30), + dateWidget(), + const SizedBox(height: 30), + detailsWidget(), + const SizedBox(height: 30), + progressWidget(ref: ref, chartData: widget.chartData), + const SizedBox(height: 30), + assigneesWidget(ref: ref, detailData: modulesProvider.moduleDetailsData['distribution']), + const SizedBox(height: 30), + statesWidget(ref: ref, detailData: modulesProvider.moduleDetailsData), + const SizedBox(height: 30), + labelsWidget(), + const SizedBox(height: 30), + links(ref: ref, context: context) + ], + ); + } + } + + Widget dateWidget() { + final modulesProvider = ref.watch(ProviderList.modulesProvider); + final themeProvider = ref.watch(ProviderList.themeProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + final detailData = modulesProvider.moduleDetailsData; + + startDate = DateFormat('yyyy-MM-dd').parse( + detailData['start_date'] == null || detailData['start_date'] == '' + ? DateTime.now().toString() + : detailData['start_date']!); + + dueDate = DateFormat('yyyy-MM-dd').parse( + detailData['end_date'] == null || detailData['end_date'] == '' + ? DateTime.now().toString() + : detailData['end_date']!); + + return Wrap( + runSpacing: 20, + children: [ + (detailData['start_date'] == null || detailData['start_date'] == '') || + (detailData['end_date'] == null || detailData['end_date'] == '') + ? Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + border: Border.all( + width: 1, + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: const CustomText( + 'Draft', + type: FontStyle.Small, + ), + ) + : Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date']) == + 'Draft' + ? themeProvider + .themeManager.tertiaryBackgroundDefaultColor + : checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date']) == + 'Completed' + ? themeProvider + .themeManager.secondaryBackgroundActiveColor + : themeProvider.themeManager.successBackgroundColor, + borderRadius: BorderRadius.circular(5)), + child: CustomText( + checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date'], + ), + type: FontStyle.Small, + color: checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date'], + ) == + 'Draft' + ? greyColor + : checkDate( + startDate: detailData['start_date'], + endDate: detailData['end_date'], + ) == + 'Completed' + ? themeProvider.themeManager.primaryColour + : greenHighLight, + ), + ), + const SizedBox(width: 20), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: () async { + if (projectProvider.role != Role.admin && + projectProvider.role != Role.member) { + CustomToast.showToast(context, + message: accessRestrictedMSG, + toastType: ToastType.failure); + return; + } + final date = await showDatePicker( + builder: (context, child) => Theme( + data: themeProvider.themeManager.datePickerThemeData, + child: child!, + ), + context: context, + initialDate: startDate!, + firstDate: DateTime(2020), + lastDate: DateTime(2025), + ); + if (date != null) { + if (dueDate != null && date.isAfter(dueDate!)) { + CustomToast.showToast(context, + message: 'Start date cannot be after end date', + toastType: ToastType.failure); + return; + } + setState(() { + startDate = date; + }); + } + + if (date != null) { + modulesProvider.updateModules( + disableLoading: true, + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projId: ref + .read(ProviderList.projectProvider) + .currentProject["id"], + moduleId: widget.moduleId, + data: {'start_date': DateFormat('yyyy-MM-dd').format(date)}, + ref: ref, + ); + } + }, + child: Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: + themeProvider.themeManager.primaryBackgroundDefaultColor, + border: Border.all( + width: 1, + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: (detailData['start_date'] == null || + detailData['start_date'] == '') || + (detailData['end_date'] == null || + detailData['end_date'] == '') + ? CustomText( + 'Start Date', + type: FontStyle.Small, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.secondaryTextColor, + ) + : Row( + children: [ + Icon(Icons.calendar_today_outlined, + size: 15, + color: themeProvider + .themeManager.placeholderTextColor), + const SizedBox(width: 7), + CustomText( + '${dateFormating(detailData['start_date'])} ', + type: FontStyle.Small, + fontWeight: FontWeightt.Regular, + color: + themeProvider.themeManager.secondaryTextColor, + ), + ], + ), + ), + ), + //arrow + const SizedBox(width: 5), + Icon( + Icons.arrow_forward, + size: 15, + color: themeProvider.themeManager.placeholderTextColor, + ), + const SizedBox(width: 5), + GestureDetector( + onTap: () async { + if (projectProvider.role != Role.admin && + projectProvider.role != Role.member) { + CustomToast.showToast(context, + message: accessRestrictedMSG, + toastType: ToastType.failure); + return; + } + final date = await showDatePicker( + builder: (context, child) => Theme( + data: themeProvider.themeManager.datePickerThemeData, + child: child!, + ), + context: context, + initialDate: dueDate!, + firstDate: startDate ?? DateTime.now(), + lastDate: DateTime(2025), + ); + + if (date != null) { + if (!date.isAfter(DateTime.now())) { + CustomToast.showToast(context, + message: 'Due date not valid ', + toastType: ToastType.failure); + return; + } + if (date.isAfter(startDate!)) { + modulesProvider.updateModules( + disableLoading: true, + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projId: ref + .read(ProviderList.projectProvider) + .currentProject["id"], + moduleId: widget.moduleId, + data: { + 'end_date': DateFormat('yyyy-MM-dd').format(date) + }, + ref: ref + ); + modulesProvider.changeTabIndex(1); + } else { + CustomToast.showToast(context, + message: 'Start date cannot be after end date ', + toastType: ToastType.failure); + } + } + }, + child: Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: + themeProvider.themeManager.primaryBackgroundDefaultColor, + border: Border.all( + width: 1, + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: (detailData['start_date'] == null || + detailData['start_date'] == '') || + (detailData['end_date'] == null || + detailData['end_date'] == '') + ? CustomText('End Date', + type: FontStyle.Small, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.secondaryTextColor) + : Row( + children: [ + Icon(Icons.calendar_today_outlined, + size: 15, + color: themeProvider + .themeManager.placeholderTextColor), + const SizedBox(width: 5), + CustomText( + '${dateFormating(detailData['end_date'])} ', + type: FontStyle.Small, + fontWeight: FontWeightt.Regular, + color: themeProvider + .themeManager.secondaryTextColor), + ], + ), + ), + ), + ], + ), + ], + ); + } + + Widget detailsWidget() { + final themeProvider = ref.watch(ProviderList.themeProvider); + final modulesProvider = ref.watch(ProviderList.modulesProvider); + return Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: CustomText( + 'Details', + type: FontStyle.Medium, + fontWeight: FontWeightt.Medium, + color: themeProvider.themeManager.primaryTextColor, + )), + const SizedBox(height: 10), + stateWidget(), + const SizedBox(height: 10), + assigneeWidget(ref: ref, detailData: modulesProvider.moduleDetailsData), + ], + ); + } + + Widget labelsWidget({bool fromModule = false}) { + final modulesProvider = ref.watch(ProviderList.modulesProvider); + final issuesProvider = ref.watch(ProviderList.issuesProvider); + final themeProvider = ref.watch(ProviderList.themeProvider); + + final detailData = modulesProvider.moduleDetailsData; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.centerLeft, + child: CustomText( + 'Labels', + type: FontStyle.Medium, + fontWeight: FontWeightt.Medium, + color: themeProvider.themeManager.primaryTextColor, + )), + const SizedBox(height: 10), + detailData['distribution']['labels'].isNotEmpty + ? Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + decoration: BoxDecoration( + color: + themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: ListView.builder( + shrinkWrap: true, + primary: false, + itemCount: detailData['distribution']['labels'].length, + itemBuilder: (context, index) { + return Container( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 8), + margin: const EdgeInsets.symmetric(vertical: 2), + decoration: BoxDecoration( + color: issuesProvider.issues.filters.labels.contains( + detailData['distribution']['labels'][index] + ['label_id']) + ? themeProvider + .themeManager.secondaryBackgroundDefaultColor + : themeProvider + .themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Icon( + Icons.circle, + size: 20, + color: detailData['distribution']['labels'] + [index]['label_name'] == + null + ? themeProvider.themeManager + .tertiaryBackgroundDefaultColor + : detailData['distribution']['labels'] + [index]['color'] == + '' || + detailData['distribution'] + ['labels'][index] + ['color'] == + null + ? themeProvider + .themeManager.placeholderTextColor + : detailData['distribution']['labels'] + [index]['color'] + .toString() + .toColor(), + ), + const SizedBox( + width: 10, + ), + SizedBox( + width: width * 0.4, + child: CustomText( + detailData['distribution']['labels'][index] + ['label_name'] ?? + 'No Label', + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + Row( + children: [ + CompletionPercentage( + value: detailData['distribution']['labels'] + [index]['completed_issues'], + totalValue: detailData['distribution'] + ['labels'][index]['total_issues']) + ], + ) + ], + ), + ); + }), + ) + : const Align( + alignment: Alignment.center, + child: CustomText('No data found'), + ) + ], + ); + } + + Widget stateWidget({bool fromModule = false}) { + final modulesProvider = ref.watch(ProviderList.modulesProvider); + final themeProvider = ref.watch(ProviderList.themeProvider); + return Container( + height: 45, + width: double.infinity, + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: Padding( + padding: const EdgeInsets.only(left: 10, right: 10), + child: Row( + children: [ + //icon + Icon( + //four squares icon + Icons.timelapse_rounded, + color: themeProvider.themeManager.placeholderTextColor), + const SizedBox(width: 15), + CustomText( + 'Progress', + type: FontStyle.Medium, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.placeholderTextColor, + ), + Expanded(child: Container()), + + CompletionPercentage( + value: modulesProvider.moduleDetailsData['completed_issues'], + totalValue: modulesProvider.moduleDetailsData['total_issues'], + ) + ], + ), + ), + ); + } + + Widget membersWidget() { + final modulesProvider = ref.watch(ProviderList.modulesProvider); + final themeProvider = ref.watch(ProviderList.themeProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + return GestureDetector( + onTap: () { + if (projectProvider.role != Role.admin && + projectProvider.role != Role.member) { + CustomToast.showToast(context, + message: accessRestrictedMSG, toastType: ToastType.failure); + return; + } + showModalBottomSheet( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.5, + ), + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + ), + context: context, + builder: (context) => const AssigneeSheet( + fromModuleDetail: false, + ), + ); + }, + child: Container( + height: 45, + width: double.infinity, + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: Padding( + padding: const EdgeInsets.only(left: 10, right: 10), + child: Row( + children: [ + //icon + Icon( + //two people icon + Icons.people_alt_rounded, + color: themeProvider.themeManager.placeholderTextColor, + ), + const SizedBox(width: 15), + CustomText( + 'Members', + type: FontStyle.Medium, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.placeholderTextColor, + ), + Expanded(child: Container()), + (modulesProvider.currentModule['members_detail'] == null || + modulesProvider.currentModule['members_detail'].isEmpty) + ? Row( + children: [ + CustomText( + 'No members', + type: FontStyle.Medium, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.primaryTextColor, + ), + const SizedBox( + width: 5, + ), + Icon( + Icons.keyboard_arrow_down, + color: themeProvider.themeManager.primaryTextColor, + ), + ], + ) + : SizedBox( + height: 27, + child: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.center, + child: SizedBox( + height: 30, + child: SquareAvatarWidget( + borderRadius: 50, + details: modulesProvider + .currentModule['members_detail']), + ), + ), + ) + ], + ), + ), + ), + ); + } + + String dateFormating(String date) { + final DateTime formatedDate = DateTime.parse(date); + final String finalDate = DateFormat('dd MMM').format(formatedDate); + return finalDate; + } + + String checkDate({required String startDate, required String endDate}) { + final DateTime now = DateTime.now(); + if ((startDate.isEmpty) || (endDate.isEmpty)) { + return 'Draft'; + } else { + if (DateTime.parse(startDate).isAfter(now)) { + final Duration difference = + DateTime.parse(startDate.split('+').first).difference(now); + if (difference.inDays == 0) { + return 'Today'; + } else { + return '${difference.inDays.abs() + 1} Days Left'; + } + } + if (DateTime.parse(startDate).isBefore(now) && + DateTime.parse(endDate).isAfter(now)) { + final Duration difference = DateTime.parse(endDate).difference(now); + if (difference.inDays == 0) { + return 'Today'; + } else { + return '${difference.inDays.abs() + 1} Days Left'; + } + } else { + return 'Completed'; + } + } + } + + String checkTimeDifferenc(String dateTime) { + final DateTime now = DateTime.now(); + final Duration difference = now.difference(DateTime.parse(dateTime)); + String? format; + + if (difference.inDays > 0) { + format = '${difference.inDays} days ago'; + } else if (difference.inHours > 0) { + format = '${difference.inHours} hours ago'; + } else if (difference.inMinutes > 0) { + format = '${difference.inMinutes} minutes ago'; + } else { + format = '${difference.inSeconds} seconds ago'; + } + + return format; + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart new file mode 100644 index 00000000..58ada121 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart @@ -0,0 +1,822 @@ +// ignore_for_file: use_build_context_synchronously + +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:loading_indicator/loading_indicator.dart'; +import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom_sheets/type_sheet.dart'; +import 'package:plane/bottom_sheets/views_sheet.dart'; +import 'package:plane/kanban/custom/board.dart'; +import 'package:plane/kanban/models/inputs.dart'; +import 'package:plane/models/chart_model.dart'; +import 'package:plane/models/issues.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_detail_page.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/calender_view.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart'; +import 'package:plane/utils/constants.dart'; +import 'package:plane/utils/custom_toast.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/custom_app_bar.dart'; +import 'package:plane/widgets/custom_text.dart'; +import 'package:plane/widgets/empty.dart'; +import '../../../../../../bottom_sheets/select_cycle_sheet.dart'; +import '../../Issues/issue_detail.dart'; + +class ModuleDetail extends ConsumerStatefulWidget { + const ModuleDetail( + {super.key, this.moduleId, this.moduleName, this.projId, this.from}); + final String? moduleName; + final String? moduleId; + final String? projId; + final PreviousScreen? from; + + @override + ConsumerState createState() => _ModuleDetailState(); +} + +class _ModuleDetailState extends ConsumerState { + List chartData = []; + PageController? pageController = PageController(); + List tempIssuesList = []; + + DateTime? dueDate; + DateTime? startDate; + + @override + void initState() { + final issuesProvider = ref.read(ProviderList.issuesProvider); + tempIssuesList = issuesProvider.issuesList; + issuesProvider.tempProjectView = issuesProvider.issues.projectView; + issuesProvider.tempGroupBy = issuesProvider.issues.groupBY; + issuesProvider.tempOrderBy = issuesProvider.issues.orderBY; + issuesProvider.tempIssueType = issuesProvider.issues.issueType; + issuesProvider.tempFilters = issuesProvider.issues.filters; + + issuesProvider.issues.projectView = IssueLayout.kanban; + issuesProvider.issues.groupBY = GroupBY.state; + + issuesProvider.issues.orderBY = OrderBY.lastCreated; + issuesProvider.issues.issueType = IssueType.all; + issuesProvider.showEmptyStates = true; + issuesProvider.issues.filters = Filters( + assignees: [], + createdBy: [], + labels: [], + priorities: [], + states: [], + targetDate: [], + startDate: [], + stateGroup: [], + subscriber: [], + ); + + WidgetsBinding.instance.addPostFrameCallback((_) async { + getModuleData(); + }); + super.initState(); + } + + Future getModuleData() async { + final modulesProvider = ref.read(ProviderList.modulesProvider); + final issuesProvider = ref.read(ProviderList.issuesProvider); + modulesProvider.moduleDetailState = StateEnum.loading; + pageController = PageController( + initialPage: modulesProvider.moduleDetailSelectedIndex, + keepPage: true, + viewportFraction: 1); + + await modulesProvider + .getModuleDetails( + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projId: widget.projId ?? + ref.read(ProviderList.projectProvider).currentProject['id'], + disableLoading: true, + moduleId: widget.moduleId!) + .then((value) => getChartData(modulesProvider + .moduleDetailsData['distribution']['completion_chart'])); + + ref + .read(ProviderList.issuesProvider) + .getIssueDisplayProperties(issueCategory: IssueCategory.cycleIssues); + await modulesProvider.getModuleView(moduleId: widget.moduleId!); + modulesProvider + .filterModuleIssues( + moduleID: widget.moduleId!, + slug: ref + .read(ProviderList.workspaceProvider) + .selectedWorkspace + .workspaceSlug, + projectId: widget.projId ?? + ref.read(ProviderList.projectProvider).currentProject['id'], + ref: ref) + .then((value) { + if (issuesProvider.issues.projectView == IssueLayout.list) { + modulesProvider.initializeBoard(); + } + }); + } + + Future getChartData(Map data) async { + data.forEach((key, value) { + chartData.add(ChartData(DateTime.parse(key), value != null ? value.toDouble() : 0.0)); + }); + } + + @override + Widget build(BuildContext context) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final issueProvider = ref.watch(ProviderList.issuesProvider); + final modulesProvider = ref.watch(ProviderList.modulesProvider); + final projectProvider = ref.read(ProviderList.projectProvider); + return WillPopScope( + onWillPop: () async { + return true; + }, + child: Scaffold( + floatingActionButton: modulesProvider.moduleIssueState == + StateEnum.loading && + (modulesProvider.moduleDetailsData['backlog_issues'] != 0 && + modulesProvider.moduleDetailsData['started_issues'] != 0 && + modulesProvider.moduleDetailsData['unstarted_issues'] != 0) + ? FloatingActionButton( + backgroundColor: themeProvider.themeManager.primaryColour, + onPressed: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: BoxConstraints( + maxHeight: height * 0.8, minHeight: 250), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + )), + context: context, + builder: (ctx) { + return const SelectCycleSheet(); + }); + }, + child: Container( + height: 50, + width: 50, + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryColour, + borderRadius: BorderRadius.circular(50), + ), + child: const Icon( + Icons.error_outline_outlined, + color: Colors.white, + ), + ), + ) + : null, + appBar: CustomAppBar( + centerTitle: true, + onPressed: () { + if (widget.from == PreviousScreen.myIssues) { + Navigator.pop(context); + return; + } + modulesProvider.changeTabIndex(0); + modulesProvider.changeState(StateEnum.empty); + Navigator.pop(context); + }, + text: widget.projId == null + ? projectProvider.currentProject['name'] + : projectProvider.projects.firstWhere( + (element) => element['id'] == widget.projId)['name'], + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 25, top: 20), + child: CustomText( + widget.moduleName!, + maxLines: 1, + type: FontStyle.H5, + fontWeight: FontWeightt.Semibold, + ), + ), + ), + ], + ), + SizedBox( + width: MediaQuery.of(context).size.width, + child: Row( + children: [ + Expanded( + child: InkWell( + onTap: () { + modulesProvider.changeTabIndex(0); + pageController!.animateToPage( + 0, + duration: const Duration(milliseconds: 100), + curve: Curves.easeIn, + ); + }, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: CustomText( + overrride: true, + 'Issues', + type: FontStyle.Large, + fontWeight: FontWeightt.Medium, + color: + modulesProvider.moduleDetailSelectedIndex == 1 + ? themeProvider + .themeManager.placeholderTextColor + : themeProvider.themeManager.primaryColour, + ), + ), + Container( + height: 7, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: + modulesProvider.moduleDetailSelectedIndex == 0 + ? themeProvider.themeManager.primaryColour + : Colors.transparent, + ), + ), + ], + ), + )), + Expanded( + child: InkWell( + onTap: () { + modulesProvider.changeTabIndex(1); + pageController!.animateToPage( + 1, + duration: const Duration(milliseconds: 100), + curve: Curves.easeIn, + ); + }, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: CustomText( + 'Details', + overrride: true, + type: FontStyle.Large, + fontWeight: FontWeightt.Medium, + color: + modulesProvider.moduleDetailSelectedIndex == 0 + ? themeProvider + .themeManager.placeholderTextColor + : themeProvider.themeManager.primaryColour, + ), + ), + Container( + height: 7, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: + modulesProvider.moduleDetailSelectedIndex == 1 + ? themeProvider.themeManager.primaryColour + : Colors.transparent, + ), + ), + ], + ), + )), + ], + ), + ), + Container( + height: 2, + width: MediaQuery.of(context).size.width, + color: themeProvider.themeManager.borderSubtle01Color, + ), + Expanded( + child: PageView( + controller: pageController, + onPageChanged: (value) { + if (value == 0) { + modulesProvider.changeTabIndex(0); + } else { + modulesProvider.changeTabIndex(1); + } + }, + children: [ + Column( + children: [ + Expanded( + child: + (modulesProvider.moduleIssueState == + StateEnum.loading || + modulesProvider.moduleDetailState == + StateEnum.loading) || + modulesProvider.moduleViewState == + StateEnum.loading + ? Center( + child: SizedBox( + width: 30, + height: 30, + child: LoadingIndicator( + indicatorType: + Indicator.lineSpinFadeLoader, + colors: [ + themeProvider + .themeManager.primaryTextColor + ], + strokeWidth: 1.0, + backgroundColor: themeProvider + .themeManager + .primaryBackgroundDefaultColor, + )), + ) + : (modulesProvider.isIssuesEmpty) + ? EmptyPlaceholder.emptyIssues(context, + moduleId: widget.moduleId, + projectId: widget.projId, + type: IssueCategory.cycleIssues, + ref: ref) + : (issueProvider.issues.projectView == + IssueLayout.list) + ? Container( + color: themeProvider.themeManager + .secondaryBackgroundDefaultColor, + margin: + const EdgeInsets.only(top: 5), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: modulesProvider + .issues.issues + .map((state) => state + .items + .isEmpty && + !modulesProvider + .showEmptyStates + ? Container() + : SizedBox( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Container( + padding: const EdgeInsets + .only( + left: + 15), + margin: const EdgeInsets + .only( + bottom: + 10), + child: Row( + children: [ + state.leading ?? + Container(), + Container( + padding: + const EdgeInsets.only( + left: + 10, + ), + width: + MediaQuery.of(context).size.width * 0.6, + child: + CustomText( + state.title!, + overflow: + TextOverflow.ellipsis, + maxLines: + 1, + type: + FontStyle.Small, + fontWeight: + FontWeightt.Medium, + ), + ), + Container( + alignment: + Alignment.center, + margin: + const EdgeInsets.only( + left: + 15, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: themeProvider.themeManager.secondaryBackgroundDefaultColor), + height: + 25, + width: + 30, + child: + CustomText( + state.items.length.toString(), + type: + FontStyle.Medium, + ), + ), + const Spacer(), + IconButton( + onPressed: + () { + if (issueProvider.issues.groupBY == GroupBY.state) { + issueProvider.createIssuedata['state'] = state.id; + } else { + issueProvider.createIssuedata['priority'] = 'de3c90cd-25cd-42ec-ac6c-a66caf8029bc'; + } + Navigator.of(context).push(MaterialPageRoute( + builder: (ctx) => CreateIssue( + moduleId: widget.moduleId, + ))); + }, + icon: + Icon( + Icons.add, + color: themeProvider.themeManager.primaryColour, + )), + const SizedBox( + width: + 10, + ), + ], + ), + ), + Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: state + .items + .map((e) => + e) + .toList()), + state.items + .isEmpty + ? Container( + margin: const EdgeInsets + .only( + bottom: 10), + width: MediaQuery.of(context) + .size + .width, + color: themeProvider + .themeManager + .primaryBackgroundDefaultColor, + padding: const EdgeInsets + .only( + top: 15, + bottom: 15, + left: 15), + child: + const CustomText( + 'No issues.', + type: + FontStyle.Small, + maxLines: + 10, + textAlign: + TextAlign.start, + ), + ) + : Container( + margin: const EdgeInsets + .only( + bottom: 10), + ) + ], + ), + )) + .toList()), + ), + ) + : issueProvider.issues.projectView == + IssueLayout.kanban + ? Padding( + padding: const EdgeInsets.only( + left: 8), + child: KanbanBoard( + modulesProvider + .initializeBoard(), + boardID: 'cycle-board', + onItemReorder: ( + {newCardIndex, + newListIndex, + oldCardIndex, + oldListIndex}) { + modulesProvider + .reorderIssue( + newCardIndex: + newCardIndex!, + newListIndex: + newListIndex!, + oldCardIndex: + oldCardIndex!, + oldListIndex: + oldListIndex!, + ) + .catchError( + (err) { + log(err.toString()); + CustomToast.showToast( + context, + message: + 'Failed to update issue', + toastType: + ToastType.failure, + ); + }, + ); + }, + isCardsDraggable: issueProvider + .checkIsCardsDaraggable(), + groupEmptyStates: + !modulesProvider + .showEmptyStates, + cardPlaceHolderColor: + themeProvider.themeManager + .primaryBackgroundDefaultColor, + cardPlaceHolderDecoration: + BoxDecoration( + color: themeProvider + .themeManager + .primaryBackgroundDefaultColor, + boxShadow: [ + BoxShadow( + blurRadius: 2, + color: themeProvider + .themeManager + .borderSubtle01Color, + spreadRadius: 0, + ) + ], + ), + backgroundColor: themeProvider + .themeManager + .secondaryBackgroundDefaultColor, + listScrollConfig: + ScrollConfig( + offset: 65, + duration: + const Duration( + milliseconds: 100, + ), + curve: Curves.linear), + listTransitionDuration: + const Duration( + milliseconds: 200), + cardTransitionDuration: + const Duration( + milliseconds: 400), + textStyle: TextStyle( + fontSize: 19, + height: 1.3, + color: + Colors.grey.shade800, + fontWeight: + FontWeight.w500), + ), + ) + : issueProvider + .issues.projectView == + IssueLayout.calendar + ? const CalendarView() + : const SpreadSheetView( + issueCategory: IssueCategory + .cycleIssues, + ), + ), + SafeArea( + child: Container( + height: 50, + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + color: themeProvider + .themeManager.primaryBackgroundDefaultColor, + boxShadow: themeProvider + .themeManager.shadowBottomControlButtons), + child: Row( + children: [ + projectProvider.role == Role.admin || + projectProvider.role == Role.member + ? Expanded( + child: GestureDetector( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => CreateIssue( + projectId: widget.projId ?? + projectProvider + .currentProject['id'], + fromMyIssues: true, + moduleId: widget.moduleId, + ), + ), + ); + }, + child: SizedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.add, + color: themeProvider + .themeManager + .primaryTextColor, + size: 20, + ), + const CustomText( + ' Issue', + type: FontStyle.Medium, + ) + ], + ), + ), + ), + ) + : Container(), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + Expanded( + child: GestureDetector( + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context) + .size + .height * + 0.85), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + )), + context: context, + builder: (ctx) { + return const TypeSheet( + issueCategory: + IssueCategory.moduleIssues, + ); + }); + }, + child: SizedBox( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.menu, + color: themeProvider + .themeManager.primaryTextColor, + size: 19, + ), + const CustomText( + ' Layout', + type: FontStyle.Medium, + ) + ], + ), + ), + )), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + issueProvider.issues.projectView == + IssueLayout.calendar + ? Container() + : Expanded( + child: GestureDetector( + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: BoxConstraints( + maxHeight: + MediaQuery.of(context) + .size + .height * + 0.9), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + )), + context: context, + builder: (ctx) { + return ViewsSheet( + projectView: issueProvider + .issues.projectView, + issueCategory: + IssueCategory.moduleIssues, + moduleId: widget.moduleId, + ); + }); + }, + child: SizedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.wysiwyg_outlined, + color: themeProvider.themeManager + .primaryTextColor, + size: 19, + ), + const CustomText( + ' Display', + type: FontStyle.Medium, + ) + ], + ), + ), + )), + Container( + height: 50, + width: 0.5, + color: themeProvider + .themeManager.borderSubtle01Color, + ), + Expanded( + child: GestureDetector( + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context) + .size + .height * + 0.85), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + )), + context: context, + builder: (ctx) { + return FilterSheet( + issueCategory: + IssueCategory.moduleIssues, + cycleOrModuleId: widget.moduleId, + ); + }); + }, + child: SizedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.filter_list_outlined, + color: themeProvider + .themeManager.primaryTextColor, + size: 19, + ), + const CustomText( + ' Filters', + type: FontStyle.Medium, + ) + ], + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ModuleDetailsPage( + moduleId: widget.moduleId!, + chartData: chartData, + ) + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/create_module.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/create_module.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_card.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_card.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_card.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_card.dart index 600bfc22..a8835190 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_card.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_card.dart @@ -4,7 +4,7 @@ import 'package:intl/intl.dart'; import 'package:plane/bottom_sheets/delete_module_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/utils/constants.dart'; import '/utils/enums.dart'; @@ -37,14 +37,13 @@ class _ModuleCardState extends ConsumerState { Navigator.push( context, MaterialPageRoute( - builder: (context) => CycleDetail( + builder: (context) => ModuleDetail( moduleId: widget.isFav ? modulesProvider.favModules[widget.index]['id'] : modulesProvider.modules[widget.index]['id'], moduleName: widget.isFav ? modulesProvider.favModules[widget.index]['name'] : modulesProvider.modules[widget.index]['name'], - fromModule: true, ), ), ); diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_screen.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_screen.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_screen.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_screen.dart index 9acb4072..e1ba440c 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/module_screen.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ModulesTab/simple_module_card.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/simple_module_card.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/empty.dart'; import 'package:plane/widgets/loading_widget.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/simple_module_card.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/simple_module_card.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/simple_module_card.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Modules/simple_module_card.dart index 089a19b3..634e08d6 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/ModulesTab/simple_module_card.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Modules/simple_module_card.dart @@ -3,11 +3,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:plane/bottom_sheets/delete_cycle_sheet.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; import 'package:plane/utils/string_manager.dart'; import '/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/widgets/custom_text.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/cycle_module_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; class SimpleModuleCard extends ConsumerStatefulWidget { const SimpleModuleCard({ @@ -36,14 +37,13 @@ class _SimpleModuleCardState extends ConsumerState { Navigator.push( context, MaterialPageRoute( - builder: (context) => CycleDetail( + builder: (context) => ModuleDetail( moduleId: widget.isFav ? modulesProvider.favModules[widget.index]['id'] : modulesProvider.modules[widget.index]['id'], moduleName: widget.isFav ? modulesProvider.favModules[widget.index]['name'] : modulesProvider.modules[widget.index]['name'], - fromModule: true, ), ), ); diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_block_card.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_block_card.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_block_card.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_block_card.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_card.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_card.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_card.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_card.dart index 2f171f25..389a7060 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_card.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_card.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:plane/bottom_sheets/delete_cycle_sheet.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Pages/page_detail.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_detail.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_detail.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_detail.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_screen.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_screen.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_screen.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_screen.dart index 382c4f5e..22992c5b 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_screen.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/PagesTab/page_card.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Pages/page_card.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/loading_widget.dart'; import 'package:plane/widgets/empty.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart index 967856b4..cb5e8721 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart @@ -209,11 +209,18 @@ class _CreateLabelState extends ConsumerState { message: "Color is not valid", toastType: ToastType.failure); } else { - - labelNotifier.createLabel({ - "name": lableController.text, - "color": '#${colorController.text}', - }); + if (widget.method == CRUD.update) { + labelNotifier.updateLabel({ + "id": widget.labelId, + "name": lableController.text, + "color": '#${colorController.text}', + }); + } else if (widget.method == CRUD.create) { + labelNotifier.createLabel({ + "name": lableController.text, + "color": '#${colorController.text}', + }); + } Navigator.of(context).pop(); } }, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/estimates_page.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/estimates_page.dart index afb88313..9baf129d 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/estimates_page.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Settings/estimates_page.dart @@ -21,8 +21,6 @@ class EstimatsPage extends ConsumerStatefulWidget { class _EstimatsPageState extends ConsumerState { @override void initState() { - log(ref.read(ProviderList.projectProvider).currentProject.toString()); - super.initState(); } diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Views/views.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Views/views.dart index 91d761f3..f6285497 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Views/views.dart @@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:plane/bottom_sheets/delete_cycle_sheet.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart rename to lib/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart index b948a593..128dc9fd 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart @@ -15,7 +15,7 @@ import '../../../../../bottom_sheets/views_sheet.dart'; import '../../../../../utils/constants.dart'; import '../../../../../utils/enums.dart'; import '../../../../../widgets/custom_text.dart'; -import '../IssuesTab/CreateIssue/create_issue.dart'; +import '../Issues/CreateIssue/create_issue.dart'; class ViewsDetail extends ConsumerStatefulWidget { const ViewsDetail( diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart b/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart index 5b8bc76a..aeb14726 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart @@ -5,7 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; import 'package:plane/bottom_sheets/views_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/calender_view.dart b/lib/screens/MainScreens/Projects/ProjectDetail/calender_view.dart index 7e66fcc2..10772c17 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/calender_view.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/calender_view.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -5,7 +7,7 @@ import 'package:intl/intl.dart'; import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; import 'package:plane/bottom_sheets/type_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; @@ -13,7 +15,7 @@ import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/square_avatar_widget.dart'; import 'package:table_calendar/table_calendar.dart'; -import 'IssuesTab/issue_detail.dart'; +import 'Issues/issue_detail.dart'; class CalendarView extends ConsumerStatefulWidget { const CalendarView({Key? key}) : super(key: key); @@ -291,6 +293,8 @@ class _DayDetailState extends ConsumerState { Widget build(BuildContext context) { final issuesProvider = ref.watch(ProviderList.issuesProvider); final themeProvider = ref.watch(ProviderList.themeProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); + return Scaffold( appBar: CustomAppBar( icon: Icons.arrow_back, @@ -346,10 +350,7 @@ class _DayDetailState extends ConsumerState { focusedDay: widget.selectedDay, calendarFormat: CalendarFormat.month, eventLoader: (day) { - return ref - .read(ProviderList.issuesProvider) - .issuesList - .where((element) { + return issuesProvider.issuesList.where((element) { if (element['target_date'] == null) return false; return DateFormat("MMM d, yyyy").format( DateTime.parse(element['target_date'])) == @@ -502,7 +503,7 @@ class _DayDetailState extends ConsumerState { Row( children: [ CustomText( - '${issuesProvider.issuesList[index]['project_detail']['identifier'].toString()} - ${issuesProvider.issuesList[index]['sequence_id']}', + '${projectProvider.currentProject['identifier'].toString()} - ${issuesProvider.issuesList[index]['sequence_id']}', type: FontStyle.Small, ), const SizedBox( diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart index e1d99a2c..40e3d2e2 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/project_details_cycles.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ViewsTab/views.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Views/views.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/empty.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart b/lib/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart index edcf9342..75be7344 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart @@ -7,7 +7,7 @@ import 'package:plane/utils/extensions/string_extensions.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/square_avatar_widget.dart'; -import 'IssuesTab/issue_detail.dart'; +import 'Issues/issue_detail.dart'; class SpreadSheetView extends ConsumerStatefulWidget { const SpreadSheetView({super.key, required this.issueCategory}); diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart new file mode 100644 index 00000000..9a0164bf --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/utils/constants.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/custom_text.dart'; +import 'package:plane/widgets/member_logo_widget.dart'; + +Widget assigneeWidget({required WidgetRef ref, required Map detailData}) { + final themeProvider = ref.watch(ProviderList.themeProvider); + + return Container( + height: 45, + width: double.infinity, + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: Padding( + padding: const EdgeInsets.only(left: 10, right: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + //icon + Icon( + //two people icon + Icons.people_outline_outlined, + color: themeProvider.themeManager.placeholderTextColor, + ), + const SizedBox(width: 15), + CustomText( + 'Lead', + type: FontStyle.Medium, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.placeholderTextColor, + ), + const Spacer(), + detailData['owned_by'] == null + ? CustomText( + 'No lead', + type: FontStyle.Medium, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.primaryTextColor, + ) + : Row( + children: [ + MemberLogoWidget( + fontType: FontStyle.Small, + boarderRadius: 50, + padding: EdgeInsets.zero, + size: 25, + imageUrl: (detailData['owned_by']['avatar']), + colorForErrorWidget: const Color.fromRGBO(55, 65, 81, 1), + memberNameFirstLetterForErrorWidget: + detailData['owned_by']['display_name'][0].toString(), + ), + const SizedBox(width: 5), + Container( + constraints: BoxConstraints(maxWidth: width * 0.4), + child: CustomText( + (detailData['owned_by'] != null && + detailData['owned_by']['display_name'] != null) + ? detailData['owned_by']['display_name'] ?? '' + : '', + type: FontStyle.Small, + maxLines: 1, + ), + ), + ], + ), + ], + ), + ), + ); +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart new file mode 100644 index 00000000..c3af11a2 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart @@ -0,0 +1,118 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/completion_percentage.dart'; +import 'package:plane/widgets/custom_text.dart'; + +Widget assigneesWidget({required WidgetRef ref, required Map detailData}) { + final issuesProvider = ref.watch(ProviderList.issuesProvider); + final themeProvider = ref.watch(ProviderList.themeProvider); + + + return Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: CustomText( + 'Assignees', + type: FontStyle.Medium, + fontWeight: FontWeightt.Medium, + color: themeProvider.themeManager.primaryTextColor, + )), + const SizedBox(height: 10), + detailData['assignees'].length == 0 + ? const CustomText('No data found.') + : Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: Column( + children: [ + ...List.generate( + detailData['assignees'].length, + (idx) { + return Container( + padding: const EdgeInsets.symmetric( + vertical: 8, horizontal: 8), + margin: const EdgeInsets.symmetric(vertical: 2), + decoration: BoxDecoration( + color: (issuesProvider.issues.filters.assignees + .contains(detailData['assignees'][idx] + ['assignee_id']) + ? themeProvider + .themeManager.secondaryBackgroundDefaultColor + : themeProvider + .themeManager.primaryBackgroundDefaultColor), + borderRadius: BorderRadius.circular(5), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Padding( + padding: const EdgeInsets.only(right: 10), + child: detailData['assignees'][idx] + ['avatar'] != + null && + detailData['assignees'][idx] + ['avatar'] != + '' + ? CircleAvatar( + radius: 10, + backgroundImage: NetworkImage( + detailData['assignees'][idx] + ['avatar']), + ) + : CircleAvatar( + radius: 10, + backgroundColor: themeProvider + .themeManager + .tertiaryBackgroundDefaultColor, + child: Center( + child: CustomText( + detailData['assignees'][idx] + ['first_name'] != + null + ? detailData['assignees'] + [idx] + ['first_name'][0] + .toString() + .toUpperCase() + : '', + type: FontStyle.Small, + ), + ), + )), + CustomText( + detailData['assignees'][idx] + ['display_name'] ?? + 'No Assignees', + color: themeProvider + .themeManager.secondaryTextColor, + ), + ], + ), + CompletionPercentage( + value: detailData['assignees'][idx] + ['completed_issues'], + totalValue: detailData['assignees'][idx] + ['total_issues'], + ) + ], + ), + ); + }, + ), + ], + ), + ), + ], + ); +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart index 9c7f506d..198bff12 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/create_cycle.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ModulesTab/create_module.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart'; import 'package:plane/screens/create_view_screen.dart'; import 'package:plane/utils/enums.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/links_widget.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/links_widget.dart new file mode 100644 index 00000000..3203a694 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/links_widget.dart @@ -0,0 +1,176 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:plane/bottom_sheets/add_link_sheet.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/custom_text.dart'; + +Widget links({required WidgetRef ref, required BuildContext context}) { + final themeProvider = ref.watch(ProviderList.themeProvider); + final moduleProvider = ref.read(ProviderList.modulesProvider); + return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomText( + 'Links', + type: FontStyle.Medium, + fontWeight: FontWeightt.Medium, + color: themeProvider.themeManager.primaryTextColor, + ), + GestureDetector( + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.85), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + )), + context: context, + builder: (ctx) { + return SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).viewInsets.bottom), + child: const AddLinkSheet(), + ), + ); + }, + ); + }, + child: Icon( + Icons.add, + color: themeProvider.themeManager.primaryTextColor, + )) + ], + ), + const SizedBox(height: 10), + moduleProvider.moduleDetailsData['link_module'].isNotEmpty + ? Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: ListView.builder( + shrinkWrap: true, + itemCount: + moduleProvider.moduleDetailsData['link_module'].length, + itemBuilder: (ctx, index) { + return SizedBox( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.only(top: 5), + child: Transform.rotate( + angle: -20, + child: Icon( + Icons.link, + color: + themeProvider.themeManager.primaryTextColor, + size: 20, + ), + ), + ), + const SizedBox( + width: 10, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + moduleProvider.moduleDetailsData['link_module'] + [index]['title'] != + null + ? CustomText( + moduleProvider + .moduleDetailsData['link_module'][index] + ['title'] + .toString(), + type: FontStyle.Medium, + ) + : Container(), + CustomText( + 'by ${moduleProvider.moduleDetailsData['link_module'][index]['created_by_detail']['display_name']}', + type: FontStyle.Small, + color: themeProvider + .themeManager.placeholderTextColor, + ) + ], + ), + const Spacer(), + GestureDetector( + onTap: () { + showModalBottomSheet( + isScrollControlled: true, + enableDrag: true, + constraints: BoxConstraints( + maxHeight: + MediaQuery.of(context).size.height * + 0.85), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(30), + topRight: Radius.circular(30), + )), + context: context, + builder: (ctx) { + return SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.of(context) + .viewInsets + .bottom), + child: AddLinkSheet( + id: moduleProvider + .moduleDetailsData['link_module'] + [index]['id'], + ), + ), + ); + }, + ); + }, + child: Icon( + Icons.edit_outlined, + color: + themeProvider.themeManager.placeholderTextColor, + size: 20, + ), + ), + const SizedBox( + width: 10, + ), + GestureDetector( + onTap: () { + moduleProvider.handleLinks( + linkID: moduleProvider + .moduleDetailsData['link_module'][index] + ['id'], + data: {}, + method: HttpMethod.delete, + context: context); + }, + child: Icon( + Icons.delete_outline, + color: + themeProvider.themeManager.placeholderTextColor, + size: 20, + ), + ), + ], + ), + ); + }), + ) + : Container() + ]); +} diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart new file mode 100644 index 00000000..7106d164 --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:intl/intl.dart'; +import 'package:plane/models/chart_model.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/custom_text.dart'; +import 'package:syncfusion_flutter_charts/charts.dart'; + + Widget progressWidget({required WidgetRef ref, required List chartData}) { + final themeProvider = ref.watch(ProviderList.themeProvider); + return Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: CustomText( + 'Progress', + type: FontStyle.Medium, + fontWeight: FontWeightt.Medium, + color: themeProvider.themeManager.primaryTextColor, + ), + ), + const SizedBox(height: 10), + Container( + padding: + const EdgeInsets.only(left: 20, right: 30, top: 35, bottom: 20), + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: SizedBox( + height: 200, + child: SfCartesianChart( + plotAreaBorderColor: Colors.transparent, + margin: EdgeInsets.zero, + primaryYAxis: NumericAxis( + majorGridLines: + const MajorGridLines(width: 0), // Remove major grid lines + ), + primaryXAxis: CategoryAxis( + labelPlacement: + LabelPlacement.betweenTicks, // Adjust label placement + interval: chartData.length > 5 ? 3 : 1, + majorGridLines: const MajorGridLines( + width: 0, + ), // Remove major grid lines + minorGridLines: const MinorGridLines(width: 0), + axisLabelFormatter: (axisLabelRenderArgs) { + return ChartAxisLabel( + DateFormat('dd MMM').format( + DateTime.parse(axisLabelRenderArgs.text), + ), + const TextStyle(fontWeight: FontWeight.normal), + ); + }, + ), + series: [ + // Renders area chart + AreaSeries( + gradient: LinearGradient( + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + colors: [ + Colors.transparent, + themeProvider.themeManager.primaryColour.withOpacity(0.2), + themeProvider.themeManager.primaryColour.withOpacity(0.3), + ], + ), + dataSource: chartData, + xValueMapper: (ChartData data, _) => data.x, + yValueMapper: (ChartData data, _) => data.y, + ), + LineSeries( + dashArray: [5.0, 5.0], + dataSource: chartData.isNotEmpty + ? [ + ChartData(chartData.first.x, + chartData.first.y), // First data point + ChartData(chartData.last.x, + 0.0), // Data point at current time with Y-value of last data point + ] + : [], + xValueMapper: (ChartData data, _) => data.x, + yValueMapper: (ChartData data, _) => data.y, + ), + ], + ), + ), + ), + ], + ); + + } diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart index d37eb90a..eee77413 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart @@ -5,7 +5,7 @@ import 'package:plane/bottom_sheets/page_filter_sheet.dart'; import 'package:plane/bottom_sheets/type_sheet.dart'; import 'package:plane/bottom_sheets/views_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; import 'package:plane/screens/MainScreens/Projects/create_page_screen.dart'; import 'package:plane/utils/bottom_sheet.helper.dart'; import 'package:plane/utils/enums.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart index c73802ec..f7276636 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart @@ -3,7 +3,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/issues_tab.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issues_tab.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/module_screen.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Views/views.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart'; @@ -82,7 +85,15 @@ class _ProjectDetailRootState extends ConsumerState { widget.onTabChange(page); }, itemBuilder: (ctx, index) { - return index == 0 ? const IssuesTab() : Container(); + return widget.selectedTab == 0 + ? const IssuesTab() + : widget.selectedTab == 1 + ? const CycleWidget() + : widget.selectedTab == 2 + ? const ModuleScreen() + : widget.selectedTab == 3 + ? const Views() + : Container(); }, itemCount: TABS.length, ), diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart new file mode 100644 index 00000000..e8f4196c --- /dev/null +++ b/lib/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:plane/provider/provider_list.dart'; +import 'package:plane/utils/constants.dart'; +import 'package:plane/utils/enums.dart'; +import 'package:plane/widgets/completion_percentage.dart'; +import 'package:plane/widgets/custom_text.dart'; + +Widget statesWidget({required WidgetRef ref, required Map detailData}) { + final List states = [ + "Backlog", + "Unstarted", + "Started", + "Cancelled", + "Completed", + ]; + final themeProvider = ref.watch(ProviderList.themeProvider); + + return Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: CustomText( + 'States', + type: FontStyle.Medium, + fontWeight: FontWeightt.Medium, + color: themeProvider.themeManager.primaryTextColor, + )), + const SizedBox(height: 10), + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: themeProvider.themeManager.primaryBackgroundDefaultColor, + borderRadius: BorderRadius.circular(5), + border: Border.all( + color: themeProvider.themeManager.borderSubtle01Color, + ), + ), + child: Column( + children: [ + ...List.generate( + states.length, + (index) => Row( + children: [ + const SizedBox(height: 50), + Padding( + padding: const EdgeInsets.only(right: 10), + child: SvgPicture.asset( + states[index] == 'Backlog' + ? 'assets/svg_images/circle.svg' + : states[index] == 'Unstarted' + ? 'assets/svg_images/in_progress.svg' + : states[index] == 'Started' + ? 'assets/svg_images/done.svg' + : states[index] == 'Cancelled' + ? 'assets/svg_images/cancelled.svg' + : 'assets/svg_images/circle.svg', + height: 22, + width: 22, + colorFilter: ColorFilter.mode( + index == 0 + ? const Color(0xFFCED4DA) + : index == 1 + ? const Color(0xFF26B5CE) + : index == 2 + ? const Color(0xFFF7AE59) + : index == 3 + ? const Color(0xFFD687FF) + : greenHighLight, + BlendMode.srcIn)), + ), + CustomText( + states[index], + type: FontStyle.Large, + fontWeight: FontWeightt.Regular, + color: themeProvider.themeManager.secondaryTextColor, + ), + const Spacer(), + index == 0 + ? CompletionPercentage( + value: detailData['backlog_issues'], + totalValue: detailData['total_issues']) + : index == 1 + ? CompletionPercentage( + value: detailData['unstarted_issues'], + totalValue: detailData['total_issues']) + : index == 2 + ? CompletionPercentage( + value: detailData['started_issues'], + totalValue: detailData['total_issues']) + : index == 3 + ? CompletionPercentage( + value: detailData['cancelled_issues'], + totalValue: detailData['total_issues']) + : CompletionPercentage( + value: detailData['completed_issues'], + totalValue: detailData['total_issues'], + ), + ], + ), + ), + ], + ), + ), + ], + ); +} diff --git a/lib/screens/MainScreens/Projects/create_project_screen.dart b/lib/screens/MainScreens/Projects/create_project_screen.dart index b5b9269a..86cdbdcd 100644 --- a/lib/screens/MainScreens/Projects/create_project_screen.dart +++ b/lib/screens/MainScreens/Projects/create_project_screen.dart @@ -51,6 +51,9 @@ class _CreateProjectState extends ConsumerState { @override void initState() { generateEmojis(); + WidgetsBinding.instance.addPostFrameCallback((_) async { + ref.read(ProviderList.projectProvider).getUnsplashImages(); + }); super.initState(); } @@ -188,8 +191,7 @@ class _CreateProjectState extends ConsumerState { enableDrag: true, isScrollControlled: true, constraints: BoxConstraints( - maxHeight: height * - 0.8, + maxHeight: height * 0.8, ), shape: const RoundedRectangleBorder( borderRadius: BorderRadius.only( diff --git a/lib/screens/on_boarding/auth/setup_workspace.dart b/lib/screens/on_boarding/auth/setup_workspace.dart index ce3542ca..66e7cfe5 100644 --- a/lib/screens/on_boarding/auth/setup_workspace.dart +++ b/lib/screens/on_boarding/auth/setup_workspace.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:plane/config/config_variables.dart'; @@ -194,7 +195,8 @@ class _SetupWorkspaceState extends ConsumerState { left: 15, ), child: CustomText( - Config.webUrl!, + // Config.webUrl!, + dotenv.env['WEB_URL'].toString(), type: FontStyle.Small, color: themeProvider.themeManager .placeholderTextColor, @@ -233,8 +235,7 @@ class _SetupWorkspaceState extends ConsumerState { onTap: () { FocusScope.of(context).unfocus(); BottomSheetHelper.showBottomSheet( - context, - const CompanySize(), + context, const CompanySize(), constraints: const BoxConstraints( maxHeight: 400, )); diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 31574fc6..f5940583 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -37,7 +37,7 @@ class _SettingScreenState extends ConsumerState 'Labels', 'Integrations', 'Estimates', - 'Automations', + // 'Automations', ]; final pageViewController = PageController(initialPage: 0); @@ -313,7 +313,7 @@ class _SettingScreenState extends ConsumerState LablesPage(), IntegrationsWidget(), EstimatsPage(), - AutomationsPage(), + // AutomationsPage(), ]), ), ], diff --git a/lib/utils/editor.dart b/lib/utils/editor.dart index 6db73deb..93330a20 100644 --- a/lib/utils/editor.dart +++ b/lib/utils/editor.dart @@ -14,7 +14,7 @@ import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'dart:developer'; -import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; class EDITOR extends ConsumerStatefulWidget { const EDITOR( diff --git a/lib/utils/issues_filter/group_by_issues.dart b/lib/utils/issues_filter/group_by_issues.dart index 42ea03aa..e23b7a75 100644 --- a/lib/utils/issues_filter/group_by_issues.dart +++ b/lib/utils/issues_filter/group_by_issues.dart @@ -1,3 +1,6 @@ +import 'dart:developer'; + +import 'package:plane/models/Project/State/states_model.dart'; import 'package:plane/utils/enums.dart'; class IssuesGroupBYHelper { @@ -10,20 +13,19 @@ class IssuesGroupBYHelper { ]; static Map> _groupByState( - List issues, Map states) { + List issues, Map states) { Map> groupedIssues = {}; - Map> stateGroups = {}; + Map> stateGroups = {}; for (final state in defaultStateGroups) { - stateGroups[state] = - states.values.where((e) => e['group'] == state).toList(); + stateGroups[state] = states.values.where((e) => e.group == state).toList(); stateGroups[state]! - .sort((a, b) => a['sequence'].compareTo(b['sequence'])); + .sort((a, b) => a.sequence.compareTo(b.sequence)); } for (final stateGroup in stateGroups.keys) { for (final state in stateGroups[stateGroup]!) { - groupedIssues[state['id']] = - issues.where((issue) => issue['state_id'] == state['id']).toList(); + groupedIssues[state.id] = + issues.where((issue) => issue['state_id'] == state.id).toList(); } } return groupedIssues; diff --git a/lib/widgets/empty.dart b/lib/widgets/empty.dart index b14e2296..2512214e 100644 --- a/lib/widgets/empty.dart +++ b/lib/widgets/empty.dart @@ -4,9 +4,9 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:plane/bottom_sheets/issues_list_sheet.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/CyclesTab/create_cycle.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/IssuesTab/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/ModulesTab/create_module.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart'; import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart'; import 'package:plane/screens/MainScreens/Projects/create_page_screen.dart'; import 'package:plane/screens/MainScreens/Projects/create_project_screen.dart'; diff --git a/lib/widgets/issue_card_widget.dart b/lib/widgets/issue_card_widget.dart index 24771d89..29da5f04 100644 --- a/lib/widgets/issue_card_widget.dart +++ b/lib/widgets/issue_card_widget.dart @@ -8,7 +8,7 @@ import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; import 'package:plane/widgets/square_avatar_widget.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/IssuesTab/issue_detail.dart'; +import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; import 'custom_rich_text.dart'; import 'custom_text.dart'; @@ -116,28 +116,28 @@ class _IssueCardWidgetState extends ConsumerState { : null, ), child: Container( - width: widget.issueCategory == IssueCategory.cycleIssues && - ref - .watch(ProviderList.issuesProvider) - .issues - .projectView == - IssueLayout.list - ? width - : widget.issueCategory == IssueCategory.moduleIssues - ? width - : widget.issueCategory == IssueCategory.cycleIssues - ? width - : widget.issueCategory == IssueCategory.myIssues - ? ref - .watch(ProviderList.myIssuesProvider) - .issues - .issues[widget.listIndex] - .width - : ref - .watch(ProviderList.issuesProvider) - .issues - .issues[0] - .width, + // width: widget.issueCategory == IssueCategory.cycleIssues && + // ref + // .watch(ProviderList.issuesProvider) + // .issues + // .projectView == + // IssueLayout.list + // ? width + // : widget.issueCategory == IssueCategory.moduleIssues + // ? width + // : widget.issueCategory == IssueCategory.cycleIssues + // ? width + // : widget.issueCategory == IssueCategory.myIssues + // ? ref + // .watch(ProviderList.myIssuesProvider) + // .issues + // .issues[widget.listIndex] + // .width + // : ref + // .watch(ProviderList.issuesProvider) + // .issues + // .issues[0] + // .width, padding: const EdgeInsets.only( left: 15.0, right: 10, @@ -650,6 +650,7 @@ class _IssueCardWidgetState extends ConsumerState { Widget listCard() { final themeProvider = ref.read(ProviderList.themeProvider); + final projectProvider = ref.watch(ProviderList.projectProvider); dynamic provider; if (widget.issueCategory == IssueCategory.cycleIssues) { provider = ref.watch(ProviderList.cyclesProvider); @@ -728,8 +729,7 @@ class _IssueCardWidgetState extends ConsumerState { color: themeProvider.themeManager.placeholderTextColor, widgets: [ TextSpan( - text: provider.issuesResponse[widget.cardIndex] - ['project_detail']['identifier'], + text: projectProvider.currentProject['identifier'], style: TextStyle( color: themeProvider .themeManager.placeholderTextColor, From 56fe587a6a9209c528d07c02ff58d530fe09f658 Mon Sep 17 00:00:00 2001 From: LAKHAN BAHETI Date: Wed, 24 Jan 2024 22:19:56 +0530 Subject: [PATCH 7/7] refactor: project files & folder re-structuring --- .../dashboard_test.dart | 8 +- lib/app.dart | 10 +- .../add_attachment_sheet.dart | 0 .../add_link_sheet.dart | 0 .../assignee_sheet.dart | 0 .../block_sheet.dart | 0 .../company_size_sheet.dart | 0 .../create_estimate.dart | 0 .../delete_cycle_sheet.dart | 0 .../delete_estimate_sheet.dart | 0 .../delete_labels_sheet.dart | 0 .../delete_leave_project_sheet.dart | 0 .../delete_module_sheet.dart | 0 .../delete_project_sheet.dart | 0 .../delete_state_sheet.dart | 0 .../delete_workspace_sheet.dart | 0 .../edit_block_sheet.dart | 0 .../edit_page_sheeet.dart | 0 .../emoji_sheet.dart | 0 .../filters/filter_sheet.dart | 2 +- .../filters/filter_sheet_state.dart | 12 +- .../filters/widgets/assigness_filter.dart | 0 .../filters/widgets/created_by_filter.dart | 0 .../filters/widgets/due_date_filter.dart | 0 .../filters/widgets/filter_buttons.dart | 0 .../filters/widgets/labels_filter.dart | 0 .../filters/widgets/priority_filter.dart | 0 .../filters/widgets/start_date_filter.dart | 0 .../filters/widgets/state_filter.dart | 0 .../global_search_sheet.dart | 30 ++- .../goto_plane_web_notifier_sheet.dart | 0 .../issue_detail_cycles_sheet.dart | 0 .../issue_detail_modules_list.dart | 0 .../issues_list_sheet.dart | 0 .../label_sheet.dart | 0 .../lead_sheet.dart | 0 .../member_status.dart | 0 .../notification_filter_sheet.dart | 2 +- .../notification_more_options_sheet.dart | 0 .../page_filter_sheet.dart | 0 .../permission_role_sheet.dart | 0 .../project_invite_memebers_sheet.dart | 14 +- .../project_lead_assignee_sheet.dart | 0 .../project_select_cover_image.dart | 0 .../role_sheet.dart | 0 .../selectProjectSheet.dart | 0 .../select_automation_state.dart | 0 .../select_cycle_sheet.dart | 0 .../select_emails.dart | 0 .../select_estimate.dart | 0 .../select_issue_labels.dart | 0 .../select_month.dart | 0 .../select_month_sheet.dart | 0 .../select_priority.dart | 0 .../select_project_members.dart | 0 .../select_states.dart | 0 .../select_workspace.dart | 2 +- .../snooze_time_sheet.dart | 0 .../status_sheet.dart | 0 .../time_zone_selector_sheet.dart | 0 .../type_sheet.dart | 0 .../views_and_layout_sheet.dart | 0 .../views_sheet.dart | 0 .../whats_new_sheet.dart | 0 .../workspace_logo.dart | 0 lib/main.dart | 2 +- lib/models/Project/Label/label.model.dart | 3 - lib/models/Project/State/states_model.dart | 42 ---- .../issue_filter_and_properties.dart | 76 +++++++ lib/models/Project/state/state_model.dart | 40 ++++ lib/models/Project/view/view_model.dart | 33 +++ lib/provider/cycles_provider.dart | 5 +- lib/provider/issue_provider.dart | 10 +- lib/provider/issues_provider.dart | 5 +- lib/provider/modules_provider.dart | 13 +- lib/provider/my_issues_provider.dart | 6 +- ...vider.dart => project_state_provider.dart} | 18 +- lib/provider/provider_list.dart | 6 +- ...ervice.dart => project_state_service.dart} | 14 +- lib/routers/generated_routes.dart | 18 +- .../Activity => activity}/activity.dart | 5 +- lib/screens/create_view_screen.dart | 2 +- .../activity_graph_wdiget.dart | 2 +- .../dash_board_screen.dart | 13 +- .../Dashboard => dashboard}/dates_model.dart | 0 lib/screens/home_screen.dart | 11 +- .../cancel_goback.dart | 0 .../import_export.dart | 10 +- .../jira_import.dart | 0 .../my_issues_screen.dart | 12 +- .../extra_notification.dart | 2 +- .../notification.dart | 6 +- .../notifications_list.dart | 5 +- .../auth/forgot_password.dart | 0 .../auth/invite_co_workers.dart | 2 +- .../auth/join_workspaces.dart | 2 +- .../auth/reset_password.dart | 0 .../auth/setup_profile_screen.dart | 8 +- .../auth/setup_workspace.dart | 5 +- .../auth/signUp.dart | 2 +- .../auth/sign_in.dart | 4 +- .../auth/sign_in_selfhosted.dart | 2 +- .../on_boarding_screen.dart | 2 +- .../workspace_invite_screen.dart | 0 .../profile_detail_screen.dart | 8 +- .../profile-settings}/profile_screen.dart | 22 +- .../user-profile}/assigned_issues.dart | 2 +- .../created_issue_page.dart.dart | 2 +- .../user-profile}/member_profile.dart | 197 +++++++++--------- .../user-profile}/over_view.dart | 6 +- .../user-profile}/subscribed_issues.dart | 2 +- .../user-profile}/user_profile.dart | 10 +- .../workpsace-settings}/invite_members.dart | 2 +- .../workpsace-settings}/members.dart | 10 +- .../workspace_general.dart | 4 +- .../archived_issues.dart | 16 +- .../create_project_screen.dart | 4 +- .../cycles}/create_cycle.dart | 0 .../cycle-detail}/cycle_details_page.dart | 14 +- .../cycle-detail}/cycle_issues_page.dart | 21 +- .../cycles}/cycle_active_card.dart | 2 +- .../cycles}/project_details_cycles.dart | 4 +- .../issue-layouts}/calender_view.dart | 11 +- .../issue-layouts}/issue_layout.dart | 8 +- .../kanban-layout}/kanban_root.dart | 0 .../issue-layouts/list-layout}/list_root.dart | 2 +- .../issue-layouts}/spreadsheet_view.dart | 3 +- .../issues}/create_issue.dart | 16 +- .../issues}/issue_detail.dart | 8 +- .../Issues => project/issues}/issues_tab.dart | 2 +- .../widgets}/selected_label_widget.dart | 0 .../models/project_detail_models.dart | 0 .../modules}/create_module.dart | 6 +- .../module-detail}/module_detail_page.dart | 23 +- .../module-detail}/module_issues_page.dart | 21 +- .../modules}/module_screen.dart | 2 +- .../modules/widgets}/module_card.dart | 5 +- .../modules/widgets}/simple_module_card.dart | 5 +- .../pages}/create_page_screen.dart | 0 .../Pages => project/pages}/page_detail.dart | 4 +- .../Pages => project/pages}/page_screen.dart | 2 +- .../pages/widgets}/page_block_card.dart | 2 +- .../pages/widgets}/page_card.dart | 4 +- .../project_detail.dart | 11 +- .../Projects => project}/project_screen.dart | 6 +- .../settings}/automations_page.dart | 4 +- .../settings}/control_page.dart | 2 +- .../settings}/create_label.dart | 0 .../settings}/estimates_page.dart | 4 +- .../settings}/features_page.dart | 0 .../settings}/general_page.dart | 6 +- .../settings}/integrations_page.dart | 0 .../settings}/lables_page.dart | 4 +- .../settings}/states_pages.dart | 5 +- .../Views => project/views}/views.dart | 4 +- .../Views => project/views}/views_detail.dart | 9 +- .../widgets/assignee_widget.dart | 0 .../widgets/assignees_widget.dart | 0 .../widgets/floating_action_button.dart | 4 +- .../widgets/links_widget.dart | 2 +- .../widgets/progress_chart.dart | 0 .../widgets/project_detail_appbar.dart | 2 +- .../project_detail_bottom_actions.dart | 15 +- .../widgets/project_detail_root.dart | 15 +- .../widgets/project_detail_tabs.dart | 2 +- .../widgets/states_widget.dart | 0 lib/screens/settings_screen.dart | 24 +-- .../{Theming => themes}/custom_theme.dart | 0 .../{Theming => themes}/prefrences.dart | 2 +- .../issue_detail_unused.dart | 20 +- lib/services/dio_service.dart | 2 +- lib/utils/editor.dart | 3 +- lib/utils/issues_filter/group_by_issues.dart | 8 +- lib/widgets/cycle_card_widget.dart | 2 +- lib/widgets/empty.dart | 14 +- lib/widgets/issue_card_widget.dart | 3 +- .../dashboard/dash_board_screen_test.dart | 8 +- 177 files changed, 588 insertions(+), 509 deletions(-) rename {integration_test => integration-tests}/dashboard_test.dart (94%) rename lib/{bottom_sheets => bottom-sheets}/add_attachment_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/add_link_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/assignee_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/block_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/company_size_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/create_estimate.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/delete_cycle_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/delete_estimate_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/delete_labels_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/delete_leave_project_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/delete_module_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/delete_project_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/delete_state_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/delete_workspace_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/edit_block_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/edit_page_sheeet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/emoji_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/filters/filter_sheet.dart (99%) rename lib/{bottom_sheets => bottom-sheets}/filters/filter_sheet_state.dart (97%) rename lib/{bottom_sheets => bottom-sheets}/filters/widgets/assigness_filter.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/filters/widgets/created_by_filter.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/filters/widgets/due_date_filter.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/filters/widgets/filter_buttons.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/filters/widgets/labels_filter.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/filters/widgets/priority_filter.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/filters/widgets/start_date_filter.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/filters/widgets/state_filter.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/global_search_sheet.dart (97%) rename lib/{bottom_sheets => bottom-sheets}/goto_plane_web_notifier_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/issue_detail_cycles_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/issue_detail_modules_list.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/issues_list_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/label_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/lead_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/member_status.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/notification_filter_sheet.dart (97%) rename lib/{bottom_sheets => bottom-sheets}/notification_more_options_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/page_filter_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/permission_role_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/project_invite_memebers_sheet.dart (97%) rename lib/{bottom_sheets => bottom-sheets}/project_lead_assignee_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/project_select_cover_image.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/role_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/selectProjectSheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_automation_state.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_cycle_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_emails.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_estimate.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_issue_labels.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_month.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_month_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_priority.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_project_members.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_states.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/select_workspace.dart (99%) rename lib/{bottom_sheets => bottom-sheets}/snooze_time_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/status_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/time_zone_selector_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/type_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/views_and_layout_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/views_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/whats_new_sheet.dart (100%) rename lib/{bottom_sheets => bottom-sheets}/workspace_logo.dart (100%) delete mode 100644 lib/models/Project/State/states_model.dart create mode 100644 lib/models/Project/issue-filter-and-properties/issue_filter_and_properties.dart create mode 100644 lib/models/Project/state/state_model.dart create mode 100644 lib/models/Project/view/view_model.dart rename lib/provider/{states_provider.dart => project_state_provider.dart} (92%) rename lib/repository/{states_service.dart => project_state_service.dart} (89%) rename lib/screens/{MainScreens/Activity => activity}/activity.dart (99%) rename lib/screens/{MainScreens/Home/Dashboard => dashboard}/activity_graph_wdiget.dart (99%) rename lib/screens/{MainScreens/Home/Dashboard => dashboard}/dash_board_screen.dart (99%) rename lib/screens/{MainScreens/Home/Dashboard => dashboard}/dates_model.dart (100%) rename lib/screens/{Import & Export => import-export}/cancel_goback.dart (100%) rename lib/screens/{Import & Export => import-export}/import_export.dart (98%) rename lib/screens/{Import & Export => import-export}/jira_import.dart (100%) rename lib/screens/{MainScreens/My_issues => my-issues}/my_issues_screen.dart (99%) rename lib/screens/{MainScreens/Notification => notifications}/extra_notification.dart (95%) rename lib/screens/{MainScreens/Notification => notifications}/notification.dart (97%) rename lib/screens/{MainScreens/Notification => notifications}/notifications_list.dart (99%) rename lib/screens/{on_boarding => onboarding}/auth/forgot_password.dart (100%) rename lib/screens/{on_boarding => onboarding}/auth/invite_co_workers.dart (99%) rename lib/screens/{on_boarding => onboarding}/auth/join_workspaces.dart (99%) rename lib/screens/{on_boarding => onboarding}/auth/reset_password.dart (100%) rename lib/screens/{on_boarding => onboarding}/auth/setup_profile_screen.dart (98%) rename lib/screens/{on_boarding => onboarding}/auth/setup_workspace.dart (99%) rename lib/screens/{on_boarding => onboarding}/auth/signUp.dart (99%) rename lib/screens/{on_boarding => onboarding}/auth/sign_in.dart (99%) rename lib/screens/{on_boarding => onboarding}/auth/sign_in_selfhosted.dart (99%) rename lib/screens/{on_boarding => onboarding}/on_boarding_screen.dart (99%) rename lib/screens/{MainScreens/Profile/ProfileSettings => profile/profile-settings}/WorkSpaceInvites/workspace_invite_screen.dart (100%) rename lib/screens/{MainScreens/Profile/ProfileSettings => profile/profile-settings}/profile_detail_screen.dart (99%) rename lib/screens/{MainScreens/Profile/ProfileSettings => profile/profile-settings}/profile_screen.dart (96%) rename lib/screens/{MainScreens/Profile/User_profile => profile/user-profile}/assigned_issues.dart (99%) rename lib/screens/{MainScreens/Profile/User_profile => profile/user-profile}/created_issue_page.dart.dart (99%) rename lib/screens/{MainScreens/Profile/User_profile => profile/user-profile}/member_profile.dart (77%) rename lib/screens/{MainScreens/Profile/User_profile => profile/user-profile}/over_view.dart (98%) rename lib/screens/{MainScreens/Profile/User_profile => profile/user-profile}/subscribed_issues.dart (99%) rename lib/screens/{MainScreens/Profile/User_profile => profile/user-profile}/user_profile.dart (93%) rename lib/screens/{MainScreens/Profile/WorkpsaceSettings => profile/workpsace-settings}/invite_members.dart (99%) rename lib/screens/{MainScreens/Profile/WorkpsaceSettings => profile/workpsace-settings}/members.dart (99%) rename lib/screens/{MainScreens/Profile/WorkpsaceSettings => profile/workpsace-settings}/workspace_general.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/archived_issues.dart (98%) rename lib/screens/{MainScreens/Projects => project}/create_project_screen.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Cycles => project/cycles}/create_cycle.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Cycles/CycleDetail => project/cycles/cycle-detail}/cycle_details_page.dart (98%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Cycles/CycleDetail => project/cycles/cycle-detail}/cycle_issues_page.dart (98%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Cycles => project/cycles}/cycle_active_card.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Cycles => project/cycles}/project_details_cycles.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project/issue-layouts}/calender_view.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Issue Layouts => project/issue-layouts}/issue_layout.dart (77%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Issue Layouts/Kanban Layout => project/issue-layouts/kanban-layout}/kanban_root.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout => project/issue-layouts/list-layout}/list_root.dart (98%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project/issue-layouts}/spreadsheet_view.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Issues/CreateIssue => project/issues}/create_issue.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Issues => project/issues}/issue_detail.dart (96%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Issues => project/issues}/issues_tab.dart (91%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Issues/CreateIssue => project/issues/widgets}/selected_label_widget.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/models/project_detail_models.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Modules => project/modules}/create_module.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Modules/ModuleDetail => project/modules/module-detail}/module_detail_page.dart (97%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Modules/ModuleDetail => project/modules/module-detail}/module_issues_page.dart (98%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Modules => project/modules}/module_screen.dart (97%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Modules => project/modules/widgets}/module_card.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Modules => project/modules/widgets}/simple_module_card.dart (98%) rename lib/screens/{MainScreens/Projects => project/pages}/create_page_screen.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Pages => project/pages}/page_detail.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Pages => project/pages}/page_screen.dart (94%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Pages => project/pages/widgets}/page_block_card.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Pages => project/pages/widgets}/page_card.dart (98%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/project_detail.dart (90%) rename lib/screens/{MainScreens/Projects => project}/project_screen.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Settings => project/settings}/automations_page.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Settings => project/settings}/control_page.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Settings => project/settings}/create_label.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Settings => project/settings}/estimates_page.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Settings => project/settings}/features_page.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Settings => project/settings}/general_page.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Settings => project/settings}/integrations_page.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Settings => project/settings}/lables_page.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Settings => project/settings}/states_pages.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Views => project/views}/views.dart (98%) rename lib/screens/{MainScreens/Projects/ProjectDetail/Views => project/views}/views_detail.dart (98%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/assignee_widget.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/assignees_widget.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/floating_action_button.dart (95%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/links_widget.dart (99%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/progress_chart.dart (100%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/project_detail_appbar.dart (96%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/project_detail_bottom_actions.dart (96%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/project_detail_root.dart (83%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/project_detail_tabs.dart (96%) rename lib/screens/{MainScreens/Projects/ProjectDetail => project}/widgets/states_widget.dart (100%) rename lib/screens/{Theming => themes}/custom_theme.dart (100%) rename lib/screens/{Theming => themes}/prefrences.dart (99%) rename lib/screens/{unused_screens => unused-screens}/issue_detail_unused.dart (99%) diff --git a/integration_test/dashboard_test.dart b/integration-tests/dashboard_test.dart similarity index 94% rename from integration_test/dashboard_test.dart rename to integration-tests/dashboard_test.dart index 688d0000..5c208e11 100644 --- a/integration_test/dashboard_test.dart +++ b/integration-tests/dashboard_test.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; -import 'package:plane/bottom_sheets/global_search_sheet.dart'; -import 'package:plane/bottom_sheets/select_workspace.dart'; +import 'package:plane/bottom-sheets/global_search_sheet.dart'; +import 'package:plane/bottom-sheets/select_workspace.dart'; import 'package:plane/models/user_profile_model.dart'; import 'package:plane/models/Workspace/workspace_model.dart'; import 'package:plane/provider/dashboard_provider.dart'; @@ -12,8 +12,8 @@ import 'package:plane/provider/profile_provider.dart'; import 'package:plane/provider/projects_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/workspace_provider.dart'; -import 'package:plane/screens/MainScreens/Home/Dashboard/dash_board_screen.dart'; -import 'package:plane/screens/on_boarding/auth/setup_workspace.dart'; +import 'package:plane/screens/dashboard/dash_board_screen.dart'; +import 'package:plane/screens/onboarding/auth/setup_workspace.dart'; import 'package:plane/utils/enums.dart'; diff --git a/lib/app.dart b/lib/app.dart index ab3fc064..796c9265 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -2,11 +2,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/provider/workspace_provider.dart'; -import 'package:plane/screens/on_boarding/auth/invite_co_workers.dart'; -import 'package:plane/screens/on_boarding/auth/join_workspaces.dart'; -import 'package:plane/screens/on_boarding/auth/setup_profile_screen.dart'; -import 'package:plane/screens/on_boarding/auth/setup_workspace.dart'; -import 'package:plane/screens/on_boarding/auth/sign_in.dart'; +import 'package:plane/screens/onboarding/auth/invite_co_workers.dart'; +import 'package:plane/screens/onboarding/auth/join_workspaces.dart'; +import 'package:plane/screens/onboarding/auth/setup_profile_screen.dart'; +import 'package:plane/screens/onboarding/auth/setup_workspace.dart'; +import 'package:plane/screens/onboarding/auth/sign_in.dart'; import 'package:plane/startup/dependency_resolver.dart'; import 'package:plane/widgets/error_state.dart'; import 'utils/enums.dart'; diff --git a/lib/bottom_sheets/add_attachment_sheet.dart b/lib/bottom-sheets/add_attachment_sheet.dart similarity index 100% rename from lib/bottom_sheets/add_attachment_sheet.dart rename to lib/bottom-sheets/add_attachment_sheet.dart diff --git a/lib/bottom_sheets/add_link_sheet.dart b/lib/bottom-sheets/add_link_sheet.dart similarity index 100% rename from lib/bottom_sheets/add_link_sheet.dart rename to lib/bottom-sheets/add_link_sheet.dart diff --git a/lib/bottom_sheets/assignee_sheet.dart b/lib/bottom-sheets/assignee_sheet.dart similarity index 100% rename from lib/bottom_sheets/assignee_sheet.dart rename to lib/bottom-sheets/assignee_sheet.dart diff --git a/lib/bottom_sheets/block_sheet.dart b/lib/bottom-sheets/block_sheet.dart similarity index 100% rename from lib/bottom_sheets/block_sheet.dart rename to lib/bottom-sheets/block_sheet.dart diff --git a/lib/bottom_sheets/company_size_sheet.dart b/lib/bottom-sheets/company_size_sheet.dart similarity index 100% rename from lib/bottom_sheets/company_size_sheet.dart rename to lib/bottom-sheets/company_size_sheet.dart diff --git a/lib/bottom_sheets/create_estimate.dart b/lib/bottom-sheets/create_estimate.dart similarity index 100% rename from lib/bottom_sheets/create_estimate.dart rename to lib/bottom-sheets/create_estimate.dart diff --git a/lib/bottom_sheets/delete_cycle_sheet.dart b/lib/bottom-sheets/delete_cycle_sheet.dart similarity index 100% rename from lib/bottom_sheets/delete_cycle_sheet.dart rename to lib/bottom-sheets/delete_cycle_sheet.dart diff --git a/lib/bottom_sheets/delete_estimate_sheet.dart b/lib/bottom-sheets/delete_estimate_sheet.dart similarity index 100% rename from lib/bottom_sheets/delete_estimate_sheet.dart rename to lib/bottom-sheets/delete_estimate_sheet.dart diff --git a/lib/bottom_sheets/delete_labels_sheet.dart b/lib/bottom-sheets/delete_labels_sheet.dart similarity index 100% rename from lib/bottom_sheets/delete_labels_sheet.dart rename to lib/bottom-sheets/delete_labels_sheet.dart diff --git a/lib/bottom_sheets/delete_leave_project_sheet.dart b/lib/bottom-sheets/delete_leave_project_sheet.dart similarity index 100% rename from lib/bottom_sheets/delete_leave_project_sheet.dart rename to lib/bottom-sheets/delete_leave_project_sheet.dart diff --git a/lib/bottom_sheets/delete_module_sheet.dart b/lib/bottom-sheets/delete_module_sheet.dart similarity index 100% rename from lib/bottom_sheets/delete_module_sheet.dart rename to lib/bottom-sheets/delete_module_sheet.dart diff --git a/lib/bottom_sheets/delete_project_sheet.dart b/lib/bottom-sheets/delete_project_sheet.dart similarity index 100% rename from lib/bottom_sheets/delete_project_sheet.dart rename to lib/bottom-sheets/delete_project_sheet.dart diff --git a/lib/bottom_sheets/delete_state_sheet.dart b/lib/bottom-sheets/delete_state_sheet.dart similarity index 100% rename from lib/bottom_sheets/delete_state_sheet.dart rename to lib/bottom-sheets/delete_state_sheet.dart diff --git a/lib/bottom_sheets/delete_workspace_sheet.dart b/lib/bottom-sheets/delete_workspace_sheet.dart similarity index 100% rename from lib/bottom_sheets/delete_workspace_sheet.dart rename to lib/bottom-sheets/delete_workspace_sheet.dart diff --git a/lib/bottom_sheets/edit_block_sheet.dart b/lib/bottom-sheets/edit_block_sheet.dart similarity index 100% rename from lib/bottom_sheets/edit_block_sheet.dart rename to lib/bottom-sheets/edit_block_sheet.dart diff --git a/lib/bottom_sheets/edit_page_sheeet.dart b/lib/bottom-sheets/edit_page_sheeet.dart similarity index 100% rename from lib/bottom_sheets/edit_page_sheeet.dart rename to lib/bottom-sheets/edit_page_sheeet.dart diff --git a/lib/bottom_sheets/emoji_sheet.dart b/lib/bottom-sheets/emoji_sheet.dart similarity index 100% rename from lib/bottom_sheets/emoji_sheet.dart rename to lib/bottom-sheets/emoji_sheet.dart diff --git a/lib/bottom_sheets/filters/filter_sheet.dart b/lib/bottom-sheets/filters/filter_sheet.dart similarity index 99% rename from lib/bottom_sheets/filters/filter_sheet.dart rename to lib/bottom-sheets/filters/filter_sheet.dart index 0f9d2cf2..e45c5bfc 100644 --- a/lib/bottom_sheets/filters/filter_sheet.dart +++ b/lib/bottom-sheets/filters/filter_sheet.dart @@ -5,7 +5,7 @@ import 'package:calendar_date_picker2/calendar_date_picker2.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:plane/models/Project/State/states_model.dart'; +import 'package:plane/models/project/state/state_model.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/cycles_provider.dart'; import 'package:plane/provider/modules_provider.dart'; diff --git a/lib/bottom_sheets/filters/filter_sheet_state.dart b/lib/bottom-sheets/filters/filter_sheet_state.dart similarity index 97% rename from lib/bottom_sheets/filters/filter_sheet_state.dart rename to lib/bottom-sheets/filters/filter_sheet_state.dart index 17c942f4..e596e2dd 100644 --- a/lib/bottom_sheets/filters/filter_sheet_state.dart +++ b/lib/bottom-sheets/filters/filter_sheet_state.dart @@ -78,8 +78,8 @@ class _FilterState { {'icon': Icons.do_disturb_alt_outlined, 'text': 'none', 'color': '#A3A3A3'} ]; - List states = [ - StatesModel.initialize().copyWith( + List states = [ + StateModel.initialize().copyWith( group: 'backlog', name: 'Backlog', color: '#5e6ad2', @@ -89,7 +89,7 @@ class _FilterState { height: 20, width: 20, )), - StatesModel.initialize().copyWith( + StateModel.initialize().copyWith( group: 'unstarted', name: 'Unstarted', color: '#eb5757', @@ -99,7 +99,7 @@ class _FilterState { height: 20, width: 20, )), - StatesModel.initialize().copyWith( + StateModel.initialize().copyWith( group: 'started', name: 'Started', color: '#26b5ce', @@ -109,7 +109,7 @@ class _FilterState { height: 20, width: 20, )), - StatesModel.initialize().copyWith( + StateModel.initialize().copyWith( group: 'completed', name: 'Completed', color: '#f2c94c', @@ -119,7 +119,7 @@ class _FilterState { height: 20, width: 20, )), - StatesModel.initialize().copyWith( + StateModel.initialize().copyWith( group: 'cancelled', name: 'Cancelled', color: '#4cb782', diff --git a/lib/bottom_sheets/filters/widgets/assigness_filter.dart b/lib/bottom-sheets/filters/widgets/assigness_filter.dart similarity index 100% rename from lib/bottom_sheets/filters/widgets/assigness_filter.dart rename to lib/bottom-sheets/filters/widgets/assigness_filter.dart diff --git a/lib/bottom_sheets/filters/widgets/created_by_filter.dart b/lib/bottom-sheets/filters/widgets/created_by_filter.dart similarity index 100% rename from lib/bottom_sheets/filters/widgets/created_by_filter.dart rename to lib/bottom-sheets/filters/widgets/created_by_filter.dart diff --git a/lib/bottom_sheets/filters/widgets/due_date_filter.dart b/lib/bottom-sheets/filters/widgets/due_date_filter.dart similarity index 100% rename from lib/bottom_sheets/filters/widgets/due_date_filter.dart rename to lib/bottom-sheets/filters/widgets/due_date_filter.dart diff --git a/lib/bottom_sheets/filters/widgets/filter_buttons.dart b/lib/bottom-sheets/filters/widgets/filter_buttons.dart similarity index 100% rename from lib/bottom_sheets/filters/widgets/filter_buttons.dart rename to lib/bottom-sheets/filters/widgets/filter_buttons.dart diff --git a/lib/bottom_sheets/filters/widgets/labels_filter.dart b/lib/bottom-sheets/filters/widgets/labels_filter.dart similarity index 100% rename from lib/bottom_sheets/filters/widgets/labels_filter.dart rename to lib/bottom-sheets/filters/widgets/labels_filter.dart diff --git a/lib/bottom_sheets/filters/widgets/priority_filter.dart b/lib/bottom-sheets/filters/widgets/priority_filter.dart similarity index 100% rename from lib/bottom_sheets/filters/widgets/priority_filter.dart rename to lib/bottom-sheets/filters/widgets/priority_filter.dart diff --git a/lib/bottom_sheets/filters/widgets/start_date_filter.dart b/lib/bottom-sheets/filters/widgets/start_date_filter.dart similarity index 100% rename from lib/bottom_sheets/filters/widgets/start_date_filter.dart rename to lib/bottom-sheets/filters/widgets/start_date_filter.dart diff --git a/lib/bottom_sheets/filters/widgets/state_filter.dart b/lib/bottom-sheets/filters/widgets/state_filter.dart similarity index 100% rename from lib/bottom_sheets/filters/widgets/state_filter.dart rename to lib/bottom-sheets/filters/widgets/state_filter.dart diff --git a/lib/bottom_sheets/global_search_sheet.dart b/lib/bottom-sheets/global_search_sheet.dart similarity index 97% rename from lib/bottom_sheets/global_search_sheet.dart rename to lib/bottom-sheets/global_search_sheet.dart index 00b2431b..0005d4bb 100644 --- a/lib/bottom_sheets/global_search_sheet.dart +++ b/lib/bottom-sheets/global_search_sheet.dart @@ -2,35 +2,33 @@ import 'dart:async'; import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/config/const.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/Import%20&%20Export/import_export.dart'; -import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/members.dart'; -import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/workspace_general.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/project_detail.dart'; -import 'package:plane/screens/MainScreens/Projects/create_project_screen.dart'; +import 'package:plane/screens/import-export/import_export.dart'; +import 'package:plane/screens/profile/workpsace-settings/members.dart'; +import 'package:plane/screens/profile/workpsace-settings/workspace_general.dart'; +import 'package:plane/screens/project/create_project_screen.dart'; +import 'package:plane/screens/project/cycles/create_cycle.dart'; +import 'package:plane/screens/project/cycles/cycle-detail/cycle_issues_page.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; +import 'package:plane/screens/project/modules/create_module.dart'; +import 'package:plane/screens/project/modules/module-detail/module_issues_page.dart'; +import 'package:plane/screens/project/project_detail.dart'; +import 'package:plane/screens/project/views/views_detail.dart'; import 'package:plane/screens/create_view_screen.dart'; import 'package:plane/screens/integrations.dart'; -import 'package:plane/screens/on_boarding/auth/join_workspaces.dart'; +import 'package:plane/screens/onboarding/auth/join_workspaces.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; - class GlobalSearchSheet extends ConsumerStatefulWidget { const GlobalSearchSheet({super.key}); @@ -450,7 +448,7 @@ class _GlobalSearchSheetState extends ConsumerState { 'title': 'Imports & Exports', 'screen': () => { Navigator.of(context).push( - MaterialPageRoute(builder: (context) => const ImportEport())) + MaterialPageRoute(builder: (context) => const ImportExport())) }, 'icon': 'assets/images/global_search_icons/imports&exports.png' }, diff --git a/lib/bottom_sheets/goto_plane_web_notifier_sheet.dart b/lib/bottom-sheets/goto_plane_web_notifier_sheet.dart similarity index 100% rename from lib/bottom_sheets/goto_plane_web_notifier_sheet.dart rename to lib/bottom-sheets/goto_plane_web_notifier_sheet.dart diff --git a/lib/bottom_sheets/issue_detail_cycles_sheet.dart b/lib/bottom-sheets/issue_detail_cycles_sheet.dart similarity index 100% rename from lib/bottom_sheets/issue_detail_cycles_sheet.dart rename to lib/bottom-sheets/issue_detail_cycles_sheet.dart diff --git a/lib/bottom_sheets/issue_detail_modules_list.dart b/lib/bottom-sheets/issue_detail_modules_list.dart similarity index 100% rename from lib/bottom_sheets/issue_detail_modules_list.dart rename to lib/bottom-sheets/issue_detail_modules_list.dart diff --git a/lib/bottom_sheets/issues_list_sheet.dart b/lib/bottom-sheets/issues_list_sheet.dart similarity index 100% rename from lib/bottom_sheets/issues_list_sheet.dart rename to lib/bottom-sheets/issues_list_sheet.dart diff --git a/lib/bottom_sheets/label_sheet.dart b/lib/bottom-sheets/label_sheet.dart similarity index 100% rename from lib/bottom_sheets/label_sheet.dart rename to lib/bottom-sheets/label_sheet.dart diff --git a/lib/bottom_sheets/lead_sheet.dart b/lib/bottom-sheets/lead_sheet.dart similarity index 100% rename from lib/bottom_sheets/lead_sheet.dart rename to lib/bottom-sheets/lead_sheet.dart diff --git a/lib/bottom_sheets/member_status.dart b/lib/bottom-sheets/member_status.dart similarity index 100% rename from lib/bottom_sheets/member_status.dart rename to lib/bottom-sheets/member_status.dart diff --git a/lib/bottom_sheets/notification_filter_sheet.dart b/lib/bottom-sheets/notification_filter_sheet.dart similarity index 97% rename from lib/bottom_sheets/notification_filter_sheet.dart rename to lib/bottom-sheets/notification_filter_sheet.dart index d582ad5a..2261a602 100644 --- a/lib/bottom_sheets/notification_filter_sheet.dart +++ b/lib/bottom-sheets/notification_filter_sheet.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Notification/extra_notification.dart'; +import 'package:plane/screens/notifications/extra_notification.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_divider.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/bottom_sheets/notification_more_options_sheet.dart b/lib/bottom-sheets/notification_more_options_sheet.dart similarity index 100% rename from lib/bottom_sheets/notification_more_options_sheet.dart rename to lib/bottom-sheets/notification_more_options_sheet.dart diff --git a/lib/bottom_sheets/page_filter_sheet.dart b/lib/bottom-sheets/page_filter_sheet.dart similarity index 100% rename from lib/bottom_sheets/page_filter_sheet.dart rename to lib/bottom-sheets/page_filter_sheet.dart diff --git a/lib/bottom_sheets/permission_role_sheet.dart b/lib/bottom-sheets/permission_role_sheet.dart similarity index 100% rename from lib/bottom_sheets/permission_role_sheet.dart rename to lib/bottom-sheets/permission_role_sheet.dart diff --git a/lib/bottom_sheets/project_invite_memebers_sheet.dart b/lib/bottom-sheets/project_invite_memebers_sheet.dart similarity index 97% rename from lib/bottom_sheets/project_invite_memebers_sheet.dart rename to lib/bottom-sheets/project_invite_memebers_sheet.dart index 57752db8..49531eb2 100644 --- a/lib/bottom_sheets/project_invite_memebers_sheet.dart +++ b/lib/bottom-sheets/project_invite_memebers_sheet.dart @@ -2,8 +2,8 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/member_status.dart'; -import 'package:plane/bottom_sheets/select_emails.dart'; +import 'package:plane/bottom-sheets/member_status.dart'; +import 'package:plane/bottom-sheets/select_emails.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; @@ -334,7 +334,7 @@ class _ProjectInviteMembersSheetState projectProvider.projectDetailModel!.name, 'INVITED_PROJECT_MEMBER': emailController.text }, - userEmail: profileProvider.userProfile.email!, + userEmail: profileProvider.userProfile.email!, userID: profileProvider.userProfile.id!); //show success snackbar @@ -343,10 +343,10 @@ class _ProjectInviteMembersSheetState toastType: ToastType.success); Navigator.pop(mainBuildContext); projectProvider.getProjectMembers( - slug: workspaceProvider - .selectedWorkspace.workspaceSlug, - projId: projectProvider.projectDetailModel!.id!, - ); + slug: workspaceProvider + .selectedWorkspace.workspaceSlug, + projId: projectProvider.projectDetailModel!.id!, + ); } else { CustomToast.showToast( mainBuildContext, diff --git a/lib/bottom_sheets/project_lead_assignee_sheet.dart b/lib/bottom-sheets/project_lead_assignee_sheet.dart similarity index 100% rename from lib/bottom_sheets/project_lead_assignee_sheet.dart rename to lib/bottom-sheets/project_lead_assignee_sheet.dart diff --git a/lib/bottom_sheets/project_select_cover_image.dart b/lib/bottom-sheets/project_select_cover_image.dart similarity index 100% rename from lib/bottom_sheets/project_select_cover_image.dart rename to lib/bottom-sheets/project_select_cover_image.dart diff --git a/lib/bottom_sheets/role_sheet.dart b/lib/bottom-sheets/role_sheet.dart similarity index 100% rename from lib/bottom_sheets/role_sheet.dart rename to lib/bottom-sheets/role_sheet.dart diff --git a/lib/bottom_sheets/selectProjectSheet.dart b/lib/bottom-sheets/selectProjectSheet.dart similarity index 100% rename from lib/bottom_sheets/selectProjectSheet.dart rename to lib/bottom-sheets/selectProjectSheet.dart diff --git a/lib/bottom_sheets/select_automation_state.dart b/lib/bottom-sheets/select_automation_state.dart similarity index 100% rename from lib/bottom_sheets/select_automation_state.dart rename to lib/bottom-sheets/select_automation_state.dart diff --git a/lib/bottom_sheets/select_cycle_sheet.dart b/lib/bottom-sheets/select_cycle_sheet.dart similarity index 100% rename from lib/bottom_sheets/select_cycle_sheet.dart rename to lib/bottom-sheets/select_cycle_sheet.dart diff --git a/lib/bottom_sheets/select_emails.dart b/lib/bottom-sheets/select_emails.dart similarity index 100% rename from lib/bottom_sheets/select_emails.dart rename to lib/bottom-sheets/select_emails.dart diff --git a/lib/bottom_sheets/select_estimate.dart b/lib/bottom-sheets/select_estimate.dart similarity index 100% rename from lib/bottom_sheets/select_estimate.dart rename to lib/bottom-sheets/select_estimate.dart diff --git a/lib/bottom_sheets/select_issue_labels.dart b/lib/bottom-sheets/select_issue_labels.dart similarity index 100% rename from lib/bottom_sheets/select_issue_labels.dart rename to lib/bottom-sheets/select_issue_labels.dart diff --git a/lib/bottom_sheets/select_month.dart b/lib/bottom-sheets/select_month.dart similarity index 100% rename from lib/bottom_sheets/select_month.dart rename to lib/bottom-sheets/select_month.dart diff --git a/lib/bottom_sheets/select_month_sheet.dart b/lib/bottom-sheets/select_month_sheet.dart similarity index 100% rename from lib/bottom_sheets/select_month_sheet.dart rename to lib/bottom-sheets/select_month_sheet.dart diff --git a/lib/bottom_sheets/select_priority.dart b/lib/bottom-sheets/select_priority.dart similarity index 100% rename from lib/bottom_sheets/select_priority.dart rename to lib/bottom-sheets/select_priority.dart diff --git a/lib/bottom_sheets/select_project_members.dart b/lib/bottom-sheets/select_project_members.dart similarity index 100% rename from lib/bottom_sheets/select_project_members.dart rename to lib/bottom-sheets/select_project_members.dart diff --git a/lib/bottom_sheets/select_states.dart b/lib/bottom-sheets/select_states.dart similarity index 100% rename from lib/bottom_sheets/select_states.dart rename to lib/bottom-sheets/select_states.dart diff --git a/lib/bottom_sheets/select_workspace.dart b/lib/bottom-sheets/select_workspace.dart similarity index 99% rename from lib/bottom_sheets/select_workspace.dart rename to lib/bottom-sheets/select_workspace.dart index c900de40..50cb93fa 100644 --- a/lib/bottom_sheets/select_workspace.dart +++ b/lib/bottom-sheets/select_workspace.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/screens/on_boarding/auth/setup_workspace.dart'; +import 'package:plane/screens/onboarding/auth/setup_workspace.dart'; import 'package:plane/utils/color_manager.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; diff --git a/lib/bottom_sheets/snooze_time_sheet.dart b/lib/bottom-sheets/snooze_time_sheet.dart similarity index 100% rename from lib/bottom_sheets/snooze_time_sheet.dart rename to lib/bottom-sheets/snooze_time_sheet.dart diff --git a/lib/bottom_sheets/status_sheet.dart b/lib/bottom-sheets/status_sheet.dart similarity index 100% rename from lib/bottom_sheets/status_sheet.dart rename to lib/bottom-sheets/status_sheet.dart diff --git a/lib/bottom_sheets/time_zone_selector_sheet.dart b/lib/bottom-sheets/time_zone_selector_sheet.dart similarity index 100% rename from lib/bottom_sheets/time_zone_selector_sheet.dart rename to lib/bottom-sheets/time_zone_selector_sheet.dart diff --git a/lib/bottom_sheets/type_sheet.dart b/lib/bottom-sheets/type_sheet.dart similarity index 100% rename from lib/bottom_sheets/type_sheet.dart rename to lib/bottom-sheets/type_sheet.dart diff --git a/lib/bottom_sheets/views_and_layout_sheet.dart b/lib/bottom-sheets/views_and_layout_sheet.dart similarity index 100% rename from lib/bottom_sheets/views_and_layout_sheet.dart rename to lib/bottom-sheets/views_and_layout_sheet.dart diff --git a/lib/bottom_sheets/views_sheet.dart b/lib/bottom-sheets/views_sheet.dart similarity index 100% rename from lib/bottom_sheets/views_sheet.dart rename to lib/bottom-sheets/views_sheet.dart diff --git a/lib/bottom_sheets/whats_new_sheet.dart b/lib/bottom-sheets/whats_new_sheet.dart similarity index 100% rename from lib/bottom_sheets/whats_new_sheet.dart rename to lib/bottom-sheets/whats_new_sheet.dart diff --git a/lib/bottom_sheets/workspace_logo.dart b/lib/bottom-sheets/workspace_logo.dart similarity index 100% rename from lib/bottom_sheets/workspace_logo.dart rename to lib/bottom-sheets/workspace_logo.dart diff --git a/lib/main.dart b/lib/main.dart index 9cb36a7e..e81835f5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,7 +5,7 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/config/config_variables.dart'; import 'package:plane/config/plane_keys.dart'; -import 'package:plane/screens/on_boarding/on_boarding_screen.dart'; +import 'package:plane/screens/onboarding/on_boarding_screen.dart'; import 'package:plane/services/shared_preference_service.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/startup/dependency_resolver.dart'; diff --git a/lib/models/Project/Label/label.model.dart b/lib/models/Project/Label/label.model.dart index fa089d48..9741773d 100644 --- a/lib/models/Project/Label/label.model.dart +++ b/lib/models/Project/Label/label.model.dart @@ -1,9 +1,6 @@ // ignore_for_file: non_constant_identifier_names import 'package:freezed_annotation/freezed_annotation.dart'; - -import 'package:plane/models/Project/project.model.dart'; -import 'package:plane/models/Workspace/workspace_model.dart'; part 'label.model.freezed.dart'; part 'label.model.g.dart'; diff --git a/lib/models/Project/State/states_model.dart b/lib/models/Project/State/states_model.dart deleted file mode 100644 index f5226238..00000000 --- a/lib/models/Project/State/states_model.dart +++ /dev/null @@ -1,42 +0,0 @@ -// ignore_for_file: non_constant_identifier_names - -import 'package:flutter/material.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -part 'states_model.freezed.dart'; -part 'states_model.g.dart'; - -@freezed -class StatesModel with _$StatesModel { - const factory StatesModel({ - required final String id, - required final String project_id, - required final String workspace_id, - required final String name, - required final String color, - required final String group, - @JsonKey(name: 'default') - required final bool is_default, - required final String? description, - required final double sequence, - @JsonKey(includeFromJson: false, includeToJson: false) - Widget? stateIcon, - }) = _StatesModel; - - factory StatesModel.fromJson(Map json) => - _$StatesModelFromJson(json); - - factory StatesModel.initialize() { - return const StatesModel( - id: '', - project_id: '', - workspace_id: '', - name: '', - color: '', - group: '', - is_default: false, - description: '', - sequence: 0, - stateIcon: null, - ); - } -} diff --git a/lib/models/Project/issue-filter-and-properties/issue_filter_and_properties.dart b/lib/models/Project/issue-filter-and-properties/issue_filter_and_properties.dart new file mode 100644 index 00000000..7bc39609 --- /dev/null +++ b/lib/models/Project/issue-filter-and-properties/issue_filter_and_properties.dart @@ -0,0 +1,76 @@ +// ignore_for_file: non_constant_identifier_names, invalid_annotation_target +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'issue_filter_and_properties.freezed.dart'; +part 'issue_filter_and_properties.g.dart'; + +@freezed +class FiltersModel with _$FiltersModel{ + + const factory FiltersModel({ + required List? priority, + required List? state, + required List? assignees, + required List? labels, + required List? created_by, + required List? target_date, + }) = _FiltersModel; + + factory FiltersModel.fromJson(Map json) => + _$FiltersModelFromJson(json); + +} + +@freezed +class DisplayFiltersModel with _$DisplayFiltersModel{ + const factory DisplayFiltersModel({ + + required String? type, + required String layout, + required String? group_by, + required String order_by, + required bool sub_issue, + required bool show_empty_groups, + required String calendar_date_range, + }) = _DisplayFiltersModel; + + factory DisplayFiltersModel.fromJson(Map json) => + _$DisplayFiltersModelFromJson(json); + +} + +@freezed +class DisplayPropertiesModel with _$DisplayPropertiesModel{ + + const factory DisplayPropertiesModel({ + @JsonKey(defaultValue: false) + required bool key, + @JsonKey(defaultValue: false) + required bool link, + @JsonKey(defaultValue: false) + required bool state, + @JsonKey(defaultValue: false) + required bool labels, + @JsonKey(defaultValue: false) + required bool assignee, + @JsonKey(defaultValue: false) + required bool due_date, + @JsonKey(defaultValue: false) + required bool estimate, + @JsonKey(defaultValue: false) + required bool priority, + @JsonKey(defaultValue: false) + required bool created_on, + @JsonKey(defaultValue: false) + required bool start_date, + @JsonKey(defaultValue: false) + required bool updated_on, + @JsonKey(defaultValue: false) + required bool sub_issue_count, + @JsonKey(defaultValue: false) + required bool attachment_count, + }) = _DisplayPropertiesModel; + + factory DisplayPropertiesModel.fromJson(Map json) => + _$DisplayPropertiesModelFromJson(json); + +} \ No newline at end of file diff --git a/lib/models/Project/state/state_model.dart b/lib/models/Project/state/state_model.dart new file mode 100644 index 00000000..4022e576 --- /dev/null +++ b/lib/models/Project/state/state_model.dart @@ -0,0 +1,40 @@ +// ignore_for_file: non_constant_identifier_names, invalid_annotation_target + +import 'package:flutter/material.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'state_model.freezed.dart'; +part 'state_model.g.dart'; + +@freezed +class StateModel with _$StateModel { + const factory StateModel({ + required final String id, + required final String project_id, + required final String workspace_id, + required final String name, + required final String color, + required final String group, + @JsonKey(name: 'default') required final bool is_default, + required final String? description, + required final double sequence, + @JsonKey(includeFromJson: false, includeToJson: false) Widget? stateIcon, + }) = _StateModel; + + factory StateModel.fromJson(Map json) => + _$StateModelFromJson(json); + + factory StateModel.initialize() { + return const StateModel( + id: '', + project_id: '', + workspace_id: '', + name: '', + color: '', + group: '', + is_default: false, + description: '', + sequence: 0, + stateIcon: null, + ); + } +} diff --git a/lib/models/Project/view/view_model.dart b/lib/models/Project/view/view_model.dart new file mode 100644 index 00000000..badb0c17 --- /dev/null +++ b/lib/models/Project/view/view_model.dart @@ -0,0 +1,33 @@ +// ignore_for_file: non_constant_identifier_names + +import 'package:plane/models/project/issue-filter-and-properties/issue_filter_and_properties.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +part 'view_model.freezed.dart'; +part 'view_model.g.dart'; + +@freezed +class ViewModel with _$ViewModel{ + + const factory ViewModel({ + required String id, + required bool is_favorite, + required String created_at, + required String updated_at, + required String name, + required String? description, + required FiltersModel filters, + required DisplayFiltersModel display_filters, + required DisplayPropertiesModel display_properties, + required int access, + required double sort_order, + required String created_by, + required String updated_by, + required String workspace, + required String project, + }) = _ViewModel; + + factory ViewModel.fromJson(Map json) => + _$ViewModelFromJson(json); + +} + diff --git a/lib/provider/cycles_provider.dart b/lib/provider/cycles_provider.dart index 790ec796..0577d932 100644 --- a/lib/provider/cycles_provider.dart +++ b/lib/provider/cycles_provider.dart @@ -10,7 +10,8 @@ import 'package:plane/config/const.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; @@ -20,8 +21,6 @@ import 'package:plane/utils/issues_filter/issue_filter.helper.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; - class CyclesProvider with ChangeNotifier { CyclesProvider(ChangeNotifierProviderRef this.ref); Ref? ref; diff --git a/lib/provider/issue_provider.dart b/lib/provider/issue_provider.dart index bf20be83..534e4739 100644 --- a/lib/provider/issue_provider.dart +++ b/lib/provider/issue_provider.dart @@ -10,19 +10,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/config/config_variables.dart'; import 'package:plane/config/const.dart'; -import 'package:plane/screens/MainScreens/Profile/User_profile/user_profile.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; +import 'package:plane/screens/profile/user-profile/user_profile.dart'; +import 'package:plane/screens/project/cycles/cycle-detail/cycle_issues_page.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; +import 'package:plane/screens/project/modules/module-detail/module_issues_page.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/config/apis.dart'; import 'package:plane/services/dio_service.dart'; import 'package:url_launcher/url_launcher.dart'; - -import '../screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; import '../utils/global_functions.dart'; -// import 'package:webview_cookie_manager/webview_cookie_manager.dart'; class IssueProvider with ChangeNotifier { IssueProvider(ChangeNotifierProviderRef this.ref); diff --git a/lib/provider/issues_provider.dart b/lib/provider/issues_provider.dart index 7f9b5742..5a302649 100644 --- a/lib/provider/issues_provider.dart +++ b/lib/provider/issues_provider.dart @@ -9,7 +9,8 @@ import 'package:plane/config/const.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; import 'package:plane/utils/global_functions.dart'; @@ -21,8 +22,6 @@ import 'package:plane/config/apis.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/enums.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; - class IssuesProvider extends ChangeNotifier { IssuesProvider(ChangeNotifierProviderRef this.ref); Ref? ref; diff --git a/lib/provider/modules_provider.dart b/lib/provider/modules_provider.dart index 358c3e6c..0e70d79e 100644 --- a/lib/provider/modules_provider.dart +++ b/lib/provider/modules_provider.dart @@ -7,7 +7,8 @@ import 'package:plane/config/apis.dart'; import 'package:plane/config/const.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; @@ -17,7 +18,6 @@ import 'package:plane/utils/global_functions.dart'; import 'package:plane/utils/issues_filter/issue_filter.helper.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; class ModuleProvider with ChangeNotifier { ModuleProvider(ChangeNotifierProviderRef this.ref); @@ -445,11 +445,10 @@ class ModuleProvider with ChangeNotifier { Issues.toOrderBY(moduleView["display_filters"]["order_by"]); issues.issueType = Issues.toIssueType(moduleView["display_filters"]["type"]); - issues.filters.priorities = - (moduleView["filters"]["priority"] == 'none' - ? [] - : moduleView["filters"]["priority"]) ?? - []; + issues.filters.priorities = (moduleView["filters"]["priority"] == 'none' + ? [] + : moduleView["filters"]["priority"]) ?? + []; issues.filters.states = moduleView["filters"]["state"] ?? []; issues.filters.assignees = moduleView["filters"]["assignees"] ?? []; issues.filters.createdBy = moduleView["filters"]["created_by"] ?? []; diff --git a/lib/provider/my_issues_provider.dart b/lib/provider/my_issues_provider.dart index 28feaf34..14925a4f 100644 --- a/lib/provider/my_issues_provider.dart +++ b/lib/provider/my_issues_provider.dart @@ -9,16 +9,14 @@ import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/profile_provider.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; -//import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/issue_card_widget.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; - class MyIssuesProvider extends ChangeNotifier { MyIssuesProvider(ChangeNotifierProviderRef this.ref); Ref? ref; diff --git a/lib/provider/states_provider.dart b/lib/provider/project_state_provider.dart similarity index 92% rename from lib/provider/states_provider.dart rename to lib/provider/project_state_provider.dart index 29dfd534..8fb30d3b 100644 --- a/lib/provider/states_provider.dart +++ b/lib/provider/project_state_provider.dart @@ -1,8 +1,8 @@ import 'dart:developer'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/models/Project/State/states_model.dart'; +import 'package:plane/models/project/state/state_model.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/repository/states_service.dart'; +import 'package:plane/repository/project_state_service.dart'; import 'package:plane/utils/enums.dart'; final defaultStateGroups = [ @@ -33,12 +33,12 @@ class StatesData { } StatesData copyWith( - {Map? states, + {Map? states, StateEnum? statesState, StateEnum? createStateLoading, StateEnum? updateState, StateEnum? deleteState, - Map>? stateGroups}) { + Map>? stateGroups}) { return StatesData( projectStates: states ?? projectStates, statesState: statesState ?? this.statesState, @@ -48,8 +48,8 @@ class StatesData { deleteState: deleteState ?? this.deleteState); } - Map projectStates = {}; - Map> stateGroups = {}; + Map projectStates = {}; + Map> stateGroups = {}; StateEnum statesState = StateEnum.empty; StateEnum createStateLoading = StateEnum.empty; StateEnum updateState = StateEnum.empty; @@ -130,11 +130,11 @@ class StatesProvider extends StateNotifier { response.fold((updateState) { final projectStates = state.projectStates; projectStates[updateState.id] = updateState; - final Map> updatedGroups = { + final Map> updatedGroups = { ...state.stateGroups }; final String groupId = updateState.group; - final List? groupStates = updatedGroups[groupId]; + final List? groupStates = updatedGroups[groupId]; if (groupStates != null) { final int indexToUpdate = groupStates.indexWhere((s) => s.id == updateState.id); @@ -167,7 +167,7 @@ class StatesProvider extends StateNotifier { delete.fold((deleted) { final projectStates = state.projectStates; projectStates.removeWhere((key, value) => key == stateId); - final Map> updatedGroups = { + final Map> updatedGroups = { ...state.stateGroups }; updatedGroups.forEach((groupId, groupStates) { diff --git a/lib/provider/provider_list.dart b/lib/provider/provider_list.dart index 8e2dc9f9..7b702c5f 100644 --- a/lib/provider/provider_list.dart +++ b/lib/provider/provider_list.dart @@ -1,5 +1,5 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/Authentication/google_sign_in.dart'; +import 'package:plane/authentication/google_sign_in.dart'; import 'package:plane/config/const.dart'; import 'package:plane/provider/activity_provider.dart'; import 'package:plane/provider/auth_provider.dart'; @@ -17,10 +17,10 @@ import 'package:plane/provider/notification_provider.dart'; import 'package:plane/provider/profile_provider.dart'; import 'package:plane/provider/projects_provider.dart'; import 'package:plane/provider/search_issue_provider.dart'; -import 'package:plane/provider/states_provider.dart'; +import 'package:plane/provider/project_state_provider.dart'; import 'package:plane/provider/whats_new_provider.dart'; import 'package:plane/provider/workspace_provider.dart'; -import 'package:plane/repository/states_service.dart'; +import 'package:plane/repository/project_state_service.dart'; import 'package:plane/repository/labels.service.dart'; import 'package:plane/services/shared_preference_service.dart'; import '../repository/dashboard_service.dart'; diff --git a/lib/repository/states_service.dart b/lib/repository/project_state_service.dart similarity index 89% rename from lib/repository/states_service.dart rename to lib/repository/project_state_service.dart index f9b41a09..dec09bc3 100644 --- a/lib/repository/states_service.dart +++ b/lib/repository/project_state_service.dart @@ -3,14 +3,14 @@ import 'dart:developer'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import 'package:plane/config/apis.dart'; -import 'package:plane/models/Project/State/states_model.dart'; +import 'package:plane/models/project/state/state_model.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/enums.dart'; class StatesService { final dio = DioConfig(); - Future, DioException>> getStates( + Future, DioException>> getStates( {required String slug, required String projectId}) async { try { final response = await dio.dioServe( @@ -52,7 +52,7 @@ class StatesService { // } final states = { for (final state in response.data) - state['id'].toString(): StatesModel.fromJson(state) + state['id'].toString(): StateModel.fromJson(state) }; return Left(states); } on DioException catch (err) { @@ -61,7 +61,7 @@ class StatesService { } } - Future> createState( + Future> createState( {required Map data, required String slug, required String projectId}) async { @@ -74,14 +74,14 @@ class StatesService { hasBody: true, httpMethod: HttpMethod.post, data: data); - return Left(StatesModel.fromJson(response.data)); + return Left(StateModel.fromJson(response.data)); } on DioException catch (err) { log(err.response.toString()); return Right(err); } } - Future> updateState( + Future> updateState( {required Map data, required String slug, required String projectId, @@ -94,7 +94,7 @@ class StatesService { hasBody: true, httpMethod: HttpMethod.patch, data: data); - return Left(StatesModel.fromJson(response.data)); + return Left(StateModel.fromJson(response.data)); } on DioException catch (err) { log(err.response.toString()); return Right(err); diff --git a/lib/routers/generated_routes.dart b/lib/routers/generated_routes.dart index cc3be09c..c4fc0a0c 100644 --- a/lib/routers/generated_routes.dart +++ b/lib/routers/generated_routes.dart @@ -1,16 +1,16 @@ import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; -import 'package:plane/screens/MainScreens/Activity/activity.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart'; -import 'package:plane/screens/MainScreens/Projects/create_project_screen.dart'; +import 'package:plane/screens/Activity/activity.dart'; +import 'package:plane/screens/project/create_project_screen.dart'; +import 'package:plane/screens/project/cycles/create_cycle.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/modules/create_module.dart'; import 'package:plane/screens/create_state.dart'; import 'package:plane/screens/home_screen.dart'; -import 'package:plane/screens/on_boarding/on_boarding_screen.dart'; -import 'package:plane/screens/on_boarding/auth/setup_profile_screen.dart'; -import 'package:plane/screens/on_boarding/auth/setup_workspace.dart'; -import 'package:plane/screens/on_boarding/auth/sign_in.dart'; +import 'package:plane/screens/onboarding/on_boarding_screen.dart'; +import 'package:plane/screens/onboarding/auth/setup_profile_screen.dart'; +import 'package:plane/screens/onboarding/auth/setup_workspace.dart'; +import 'package:plane/screens/onboarding/auth/sign_in.dart'; import 'package:plane/utils/page_route_builder.dart'; import 'routes_path.dart'; diff --git a/lib/screens/MainScreens/Activity/activity.dart b/lib/screens/activity/activity.dart similarity index 99% rename from lib/screens/MainScreens/Activity/activity.dart rename to lib/screens/activity/activity.dart index 412b7f20..33ba11c6 100644 --- a/lib/screens/MainScreens/Activity/activity.dart +++ b/lib/screens/activity/activity.dart @@ -5,7 +5,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Profile/User_profile/user_profile.dart'; +import 'package:plane/screens/profile/user-profile/user_profile.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; @@ -16,8 +17,6 @@ import 'package:plane/widgets/error_state.dart'; import 'package:plane/widgets/loading_widget.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../Projects/ProjectDetail/Issues/issue_detail.dart'; - class Activity extends ConsumerStatefulWidget { const Activity({super.key}); diff --git a/lib/screens/create_view_screen.dart b/lib/screens/create_view_screen.dart index 5fb1cc98..2abf5bfc 100644 --- a/lib/screens/create_view_screen.dart +++ b/lib/screens/create_view_screen.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom-sheets/filters/filter_sheet.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; diff --git a/lib/screens/MainScreens/Home/Dashboard/activity_graph_wdiget.dart b/lib/screens/dashboard/activity_graph_wdiget.dart similarity index 99% rename from lib/screens/MainScreens/Home/Dashboard/activity_graph_wdiget.dart rename to lib/screens/dashboard/activity_graph_wdiget.dart index 7d545add..b7b0a9fa 100644 --- a/lib/screens/MainScreens/Home/Dashboard/activity_graph_wdiget.dart +++ b/lib/screens/dashboard/activity_graph_wdiget.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Home/Dashboard/dates_model.dart'; +import 'package:plane/screens/dashboard/dates_model.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Home/Dashboard/dash_board_screen.dart b/lib/screens/dashboard/dash_board_screen.dart similarity index 99% rename from lib/screens/MainScreens/Home/Dashboard/dash_board_screen.dart rename to lib/screens/dashboard/dash_board_screen.dart index 9a2ac91e..5e68ff32 100644 --- a/lib/screens/MainScreens/Home/Dashboard/dash_board_screen.dart +++ b/lib/screens/dashboard/dash_board_screen.dart @@ -4,29 +4,28 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; -import 'package:plane/bottom_sheets/select_month_sheet.dart'; -import 'package:plane/screens/MainScreens/Home/Dashboard/activity_graph_wdiget.dart'; +import 'package:plane/bottom-sheets/select_month_sheet.dart'; +import 'package:plane/screens/dashboard/activity_graph_wdiget.dart'; +import 'package:plane/screens/onboarding/auth/setup_workspace.dart'; +import 'package:plane/screens/project/create_project_screen.dart'; import 'package:plane/utils/string_manager.dart'; import 'package:plane/widgets/padding_widget.dart'; import 'package:plane/widgets/workspace_logo_for_diffrent_extensions.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; import 'package:url_launcher/url_launcher.dart'; -import 'package:plane/bottom_sheets/global_search_sheet.dart'; -import 'package:plane/bottom_sheets/select_workspace.dart'; +import 'package:plane/bottom-sheets/global_search_sheet.dart'; +import 'package:plane/bottom-sheets/select_workspace.dart'; import 'package:plane/provider/dashboard_provider.dart'; import 'package:plane/provider/profile_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; -import 'package:plane/screens/MainScreens/Projects/create_project_screen.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/global_functions.dart'; import 'package:plane/utils/time_manager.dart'; import 'package:plane/widgets/custom_text.dart'; -import '../../../on_boarding/auth/setup_workspace.dart'; - class DashBoardScreen extends ConsumerStatefulWidget { final bool fromSignUp; const DashBoardScreen({required this.fromSignUp, super.key}); diff --git a/lib/screens/MainScreens/Home/Dashboard/dates_model.dart b/lib/screens/dashboard/dates_model.dart similarity index 100% rename from lib/screens/MainScreens/Home/Dashboard/dates_model.dart rename to lib/screens/dashboard/dates_model.dart diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 9847fcf4..0d05025a 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -1,18 +1,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:plane/screens/MainScreens/My_issues/my_issues_screen.dart'; -import 'package:plane/screens/MainScreens/Notification/notification.dart'; -import 'package:plane/screens/MainScreens/Profile/ProfileSettings/profile_screen.dart'; +import 'package:plane/screens/dashboard/dash_board_screen.dart'; +import 'package:plane/screens/my-issues/my_issues_screen.dart'; +import 'package:plane/screens/notifications/notification.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/profile/profile-settings/profile_screen.dart'; +import 'package:plane/screens/project/project_screen.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/error_state.dart'; -import 'MainScreens/Home/Dashboard/dash_board_screen.dart'; -import 'MainScreens/Projects/project_screen.dart'; - class HomeScreen extends ConsumerStatefulWidget { const HomeScreen({required this.fromSignUp, super.key}); final bool fromSignUp; diff --git a/lib/screens/Import & Export/cancel_goback.dart b/lib/screens/import-export/cancel_goback.dart similarity index 100% rename from lib/screens/Import & Export/cancel_goback.dart rename to lib/screens/import-export/cancel_goback.dart diff --git a/lib/screens/Import & Export/import_export.dart b/lib/screens/import-export/import_export.dart similarity index 98% rename from lib/screens/Import & Export/import_export.dart rename to lib/screens/import-export/import_export.dart index 6fde9e66..6d315ef6 100644 --- a/lib/screens/Import & Export/import_export.dart +++ b/lib/screens/import-export/import_export.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/goto_plane_web_notifier_sheet.dart'; +import 'package:plane/bottom-sheets/goto_plane_web_notifier_sheet.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/loading_widget.dart'; @@ -8,14 +8,14 @@ import 'package:plane/provider/provider_list.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:url_launcher/url_launcher.dart'; -class ImportEport extends ConsumerStatefulWidget { - const ImportEport({super.key}); +class ImportExport extends ConsumerStatefulWidget { + const ImportExport({super.key}); @override - ConsumerState createState() => _ImportEportState(); + ConsumerState createState() => _ImportEportState(); } -class _ImportEportState extends ConsumerState { +class _ImportEportState extends ConsumerState { @override void initState() { final prov = ref.read(ProviderList.integrationProvider); diff --git a/lib/screens/Import & Export/jira_import.dart b/lib/screens/import-export/jira_import.dart similarity index 100% rename from lib/screens/Import & Export/jira_import.dart rename to lib/screens/import-export/jira_import.dart diff --git a/lib/screens/MainScreens/My_issues/my_issues_screen.dart b/lib/screens/my-issues/my_issues_screen.dart similarity index 99% rename from lib/screens/MainScreens/My_issues/my_issues_screen.dart rename to lib/screens/my-issues/my_issues_screen.dart index d813da0f..339f4e2c 100644 --- a/lib/screens/MainScreens/My_issues/my_issues_screen.dart +++ b/lib/screens/my-issues/my_issues_screen.dart @@ -1,22 +1,20 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; -import 'package:plane/bottom_sheets/global_search_sheet.dart'; -import 'package:plane/bottom_sheets/views_and_layout_sheet.dart'; +import 'package:plane/bottom-sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom-sheets/global_search_sheet.dart'; +import 'package:plane/bottom-sheets/views_and_layout_sheet.dart'; import 'package:plane/kanban/custom/board.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; - +import 'package:plane/screens/project/issues/create_issue.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/empty.dart'; import 'package:plane/widgets/loading_widget.dart'; - -import '../../../provider/profile_provider.dart'; +import '../../provider/profile_provider.dart'; class MyIssuesScreen extends ConsumerStatefulWidget { const MyIssuesScreen({super.key}); diff --git a/lib/screens/MainScreens/Notification/extra_notification.dart b/lib/screens/notifications/extra_notification.dart similarity index 95% rename from lib/screens/MainScreens/Notification/extra_notification.dart rename to lib/screens/notifications/extra_notification.dart index 768724f7..5d386a44 100644 --- a/lib/screens/MainScreens/Notification/extra_notification.dart +++ b/lib/screens/notifications/extra_notification.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Notification/notifications_list.dart'; +import 'package:plane/screens/notifications/notifications_list.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/loading_widget.dart'; diff --git a/lib/screens/MainScreens/Notification/notification.dart b/lib/screens/notifications/notification.dart similarity index 97% rename from lib/screens/MainScreens/Notification/notification.dart rename to lib/screens/notifications/notification.dart index 929421b8..cbaa54da 100644 --- a/lib/screens/MainScreens/Notification/notification.dart +++ b/lib/screens/notifications/notification.dart @@ -3,10 +3,10 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:plane/bottom_sheets/notification_filter_sheet.dart'; -import 'package:plane/bottom_sheets/notification_more_options_sheet.dart'; +import 'package:plane/bottom-sheets/notification_filter_sheet.dart'; +import 'package:plane/bottom-sheets/notification_more_options_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Notification/notifications_list.dart'; +import 'package:plane/screens/notifications/notifications_list.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/custom_divider.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Notification/notifications_list.dart b/lib/screens/notifications/notifications_list.dart similarity index 99% rename from lib/screens/MainScreens/Notification/notifications_list.dart rename to lib/screens/notifications/notifications_list.dart index f5225e8c..6cdbd6b6 100644 --- a/lib/screens/MainScreens/Notification/notifications_list.dart +++ b/lib/screens/notifications/notifications_list.dart @@ -2,8 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:intl/intl.dart'; -import 'package:plane/bottom_sheets/snooze_time_sheet.dart'; +import 'package:plane/bottom-sheets/snooze_time_sheet.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_rich_text.dart'; @@ -12,8 +13,6 @@ import 'package:plane/widgets/empty.dart'; import 'package:plane/widgets/error_state.dart'; import 'package:plane/widgets/loading_widget.dart'; -import '../Projects/ProjectDetail/Issues/issue_detail.dart'; - class NotificationsList extends ConsumerStatefulWidget { const NotificationsList({super.key, required this.data, required this.type}); final List data; diff --git a/lib/screens/on_boarding/auth/forgot_password.dart b/lib/screens/onboarding/auth/forgot_password.dart similarity index 100% rename from lib/screens/on_boarding/auth/forgot_password.dart rename to lib/screens/onboarding/auth/forgot_password.dart diff --git a/lib/screens/on_boarding/auth/invite_co_workers.dart b/lib/screens/onboarding/auth/invite_co_workers.dart similarity index 99% rename from lib/screens/on_boarding/auth/invite_co_workers.dart rename to lib/screens/onboarding/auth/invite_co_workers.dart index 8478305f..36336d15 100644 --- a/lib/screens/on_boarding/auth/invite_co_workers.dart +++ b/lib/screens/onboarding/auth/invite_co_workers.dart @@ -2,7 +2,7 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:plane/bottom_sheets/permission_role_sheet.dart'; +import 'package:plane/bottom-sheets/permission_role_sheet.dart'; import 'package:plane/screens/home_screen.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/loading_widget.dart'; diff --git a/lib/screens/on_boarding/auth/join_workspaces.dart b/lib/screens/onboarding/auth/join_workspaces.dart similarity index 99% rename from lib/screens/on_boarding/auth/join_workspaces.dart rename to lib/screens/onboarding/auth/join_workspaces.dart index 5aafa177..82a3d8bc 100644 --- a/lib/screens/on_boarding/auth/join_workspaces.dart +++ b/lib/screens/onboarding/auth/join_workspaces.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/on_boarding/auth/setup_workspace.dart'; +import 'package:plane/screens/onboarding/auth/setup_workspace.dart'; import 'package:plane/utils/color_manager.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; diff --git a/lib/screens/on_boarding/auth/reset_password.dart b/lib/screens/onboarding/auth/reset_password.dart similarity index 100% rename from lib/screens/on_boarding/auth/reset_password.dart rename to lib/screens/onboarding/auth/reset_password.dart diff --git a/lib/screens/on_boarding/auth/setup_profile_screen.dart b/lib/screens/onboarding/auth/setup_profile_screen.dart similarity index 98% rename from lib/screens/on_boarding/auth/setup_profile_screen.dart rename to lib/screens/onboarding/auth/setup_profile_screen.dart index 2fe2b7d0..a05d3daa 100644 --- a/lib/screens/on_boarding/auth/setup_profile_screen.dart +++ b/lib/screens/onboarding/auth/setup_profile_screen.dart @@ -3,18 +3,18 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:plane/bottom_sheets/time_zone_selector_sheet.dart'; -import 'package:plane/screens/on_boarding/auth/join_workspaces.dart'; +import 'package:plane/bottom-sheets/time_zone_selector_sheet.dart'; +import 'package:plane/screens/onboarding/auth/join_workspaces.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/on_boarding/auth/setup_workspace.dart'; +import 'package:plane/screens/onboarding/auth/setup_workspace.dart'; import 'package:plane/utils/timezone_manager.dart'; import 'package:plane/widgets/loading_widget.dart'; // import '../Provider/provider_list.dart'; import '../../../widgets/custom_button.dart'; import '../../../widgets/custom_rich_text.dart'; -import '../../../bottom_sheets/role_sheet.dart'; +import '../../../bottom-sheets/role_sheet.dart'; import '../../../widgets/custom_text.dart'; class SetupProfileScreen extends ConsumerStatefulWidget { diff --git a/lib/screens/on_boarding/auth/setup_workspace.dart b/lib/screens/onboarding/auth/setup_workspace.dart similarity index 99% rename from lib/screens/on_boarding/auth/setup_workspace.dart rename to lib/screens/onboarding/auth/setup_workspace.dart index 66e7cfe5..e7463450 100644 --- a/lib/screens/on_boarding/auth/setup_workspace.dart +++ b/lib/screens/onboarding/auth/setup_workspace.dart @@ -5,8 +5,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:plane/config/config_variables.dart'; -import 'package:plane/screens/on_boarding/auth/invite_co_workers.dart'; +import 'package:plane/screens/onboarding/auth/invite_co_workers.dart'; import 'package:plane/utils/bottom_sheet.helper.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; @@ -14,7 +13,7 @@ import 'package:plane/widgets/custom_rich_text.dart'; import 'package:plane/widgets/loading_widget.dart'; import '../../../provider/provider_list.dart'; import '../../../widgets/custom_button.dart'; -import '../../../bottom_sheets/company_size_sheet.dart'; +import '../../../bottom-sheets/company_size_sheet.dart'; import '../../../widgets/custom_text.dart'; class SetupWorkspace extends ConsumerStatefulWidget { diff --git a/lib/screens/on_boarding/auth/signUp.dart b/lib/screens/onboarding/auth/signUp.dart similarity index 99% rename from lib/screens/on_boarding/auth/signUp.dart rename to lib/screens/onboarding/auth/signUp.dart index 224835dd..b4344c86 100644 --- a/lib/screens/on_boarding/auth/signUp.dart +++ b/lib/screens/onboarding/auth/signUp.dart @@ -5,7 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/screens/home_screen.dart'; -import 'package:plane/screens/on_boarding/auth/setup_profile_screen.dart'; +import 'package:plane/screens/onboarding/auth/setup_profile_screen.dart'; import 'package:plane/widgets/custom_button.dart'; import 'package:plane/widgets/custom_rich_text.dart'; import 'package:plane/widgets/loading_widget.dart'; diff --git a/lib/screens/on_boarding/auth/sign_in.dart b/lib/screens/onboarding/auth/sign_in.dart similarity index 99% rename from lib/screens/on_boarding/auth/sign_in.dart rename to lib/screens/onboarding/auth/sign_in.dart index aa60fe64..d6d4103f 100644 --- a/lib/screens/on_boarding/auth/sign_in.dart +++ b/lib/screens/onboarding/auth/sign_in.dart @@ -8,13 +8,13 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:google_sign_in/google_sign_in.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/Authentication/google_sign_in.dart'; +import 'package:plane/authentication/google_sign_in.dart'; import 'package:plane/config/config_variables.dart'; import 'package:plane/mixins/widget_state_mixin.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/screens/home_screen.dart'; -import 'package:plane/screens/on_boarding/auth/setup_profile_screen.dart'; +import 'package:plane/screens/onboarding/auth/setup_profile_screen.dart'; import 'package:plane/utils/global_functions.dart'; import 'package:plane/widgets/custom_button.dart'; import 'package:plane/utils/constants.dart'; diff --git a/lib/screens/on_boarding/auth/sign_in_selfhosted.dart b/lib/screens/onboarding/auth/sign_in_selfhosted.dart similarity index 99% rename from lib/screens/on_boarding/auth/sign_in_selfhosted.dart rename to lib/screens/onboarding/auth/sign_in_selfhosted.dart index 3d40c2f1..d71c5faa 100644 --- a/lib/screens/on_boarding/auth/sign_in_selfhosted.dart +++ b/lib/screens/onboarding/auth/sign_in_selfhosted.dart @@ -5,7 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/screens/home_screen.dart'; -import 'package:plane/screens/on_boarding/auth/setup_profile_screen.dart'; +import 'package:plane/screens/onboarding/auth/setup_profile_screen.dart'; import 'package:plane/widgets/custom_button.dart'; import 'package:plane/widgets/custom_rich_text.dart'; import 'package:plane/widgets/loading_widget.dart'; diff --git a/lib/screens/on_boarding/on_boarding_screen.dart b/lib/screens/onboarding/on_boarding_screen.dart similarity index 99% rename from lib/screens/on_boarding/on_boarding_screen.dart rename to lib/screens/onboarding/on_boarding_screen.dart index db865dbd..4ed025b6 100644 --- a/lib/screens/on_boarding/on_boarding_screen.dart +++ b/lib/screens/onboarding/on_boarding_screen.dart @@ -3,7 +3,7 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:plane/config/const.dart'; -import 'package:plane/screens/on_boarding/auth/signUp.dart'; +import 'package:plane/screens/onboarding/auth/signUp.dart'; import 'package:plane/utils/constants.dart'; import '../../provider/provider_list.dart'; import '../../widgets/custom_button.dart'; diff --git a/lib/screens/MainScreens/Profile/ProfileSettings/WorkSpaceInvites/workspace_invite_screen.dart b/lib/screens/profile/profile-settings/WorkSpaceInvites/workspace_invite_screen.dart similarity index 100% rename from lib/screens/MainScreens/Profile/ProfileSettings/WorkSpaceInvites/workspace_invite_screen.dart rename to lib/screens/profile/profile-settings/WorkSpaceInvites/workspace_invite_screen.dart diff --git a/lib/screens/MainScreens/Profile/ProfileSettings/profile_detail_screen.dart b/lib/screens/profile/profile-settings/profile_detail_screen.dart similarity index 99% rename from lib/screens/MainScreens/Profile/ProfileSettings/profile_detail_screen.dart rename to lib/screens/profile/profile-settings/profile_detail_screen.dart index 42ea362a..df6f98b3 100644 --- a/lib/screens/MainScreens/Profile/ProfileSettings/profile_detail_screen.dart +++ b/lib/screens/profile/profile-settings/profile_detail_screen.dart @@ -8,22 +8,22 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:image_picker/image_picker.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/time_zone_selector_sheet.dart'; +import 'package:plane/bottom-sheets/time_zone_selector_sheet.dart'; import 'package:plane/config/const.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/Theming/prefrences.dart'; +import 'package:plane/screens/themes/prefrences.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/timezone_manager.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/custom_button.dart'; -import 'package:plane/bottom_sheets/role_sheet.dart'; +import 'package:plane/bottom-sheets/role_sheet.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/loading_widget.dart'; import 'package:plane/widgets/shimmer_effect_widget.dart'; -import '../../../../widgets/custom_rich_text.dart'; +import '../../../widgets/custom_rich_text.dart'; class ProfileDetailScreen extends ConsumerStatefulWidget { const ProfileDetailScreen({super.key}); diff --git a/lib/screens/MainScreens/Profile/ProfileSettings/profile_screen.dart b/lib/screens/profile/profile-settings/profile_screen.dart similarity index 96% rename from lib/screens/MainScreens/Profile/ProfileSettings/profile_screen.dart rename to lib/screens/profile/profile-settings/profile_screen.dart index 39d74bb0..6e15e478 100644 --- a/lib/screens/MainScreens/Profile/ProfileSettings/profile_screen.dart +++ b/lib/screens/profile/profile-settings/profile_screen.dart @@ -2,25 +2,25 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/select_workspace.dart'; +import 'package:plane/bottom-sheets/select_workspace.dart'; import 'package:plane/provider/profile_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; import 'package:plane/provider/workspace_provider.dart'; -import 'package:plane/screens/Import%20&%20Export/import_export.dart'; -import 'package:plane/screens/MainScreens/Activity/activity.dart'; -import 'package:plane/screens/MainScreens/Profile/User_profile/user_profile.dart'; -import 'package:plane/screens/Theming/prefrences.dart'; +import 'package:plane/screens/Activity/activity.dart'; +import 'package:plane/screens/import-export/import_export.dart'; +import 'package:plane/screens/profile/profile-settings/profile_detail_screen.dart'; +import 'package:plane/screens/profile/user-profile/user_profile.dart'; +import 'package:plane/screens/profile/workpsace-settings/members.dart'; +import 'package:plane/screens/profile/workpsace-settings/workspace_general.dart'; +import 'package:plane/screens/themes/prefrences.dart'; import 'package:plane/screens/integrations.dart'; -import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/members.dart'; -import 'package:plane/screens/MainScreens/Profile/ProfileSettings/profile_detail_screen.dart'; -import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/workspace_general.dart'; -import 'package:plane/screens/on_boarding/auth/join_workspaces.dart'; +import 'package:plane/screens/onboarding/auth/join_workspaces.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_button.dart'; -import 'package:plane/screens/on_boarding/on_boarding_screen.dart'; +import 'package:plane/screens/onboarding/on_boarding_screen.dart'; import 'package:plane/widgets/custom_divider.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/padding_widget.dart'; @@ -135,7 +135,7 @@ class _ProfileScreenState extends ConsumerState { Navigator.push( context, MaterialPageRoute( - builder: (context) => const ImportEport(), + builder: (context) => const ImportExport(), ), ); } diff --git a/lib/screens/MainScreens/Profile/User_profile/assigned_issues.dart b/lib/screens/profile/user-profile/assigned_issues.dart similarity index 99% rename from lib/screens/MainScreens/Profile/User_profile/assigned_issues.dart rename to lib/screens/profile/user-profile/assigned_issues.dart index 13c4bce6..b2d2a156 100644 --- a/lib/screens/MainScreens/Profile/User_profile/assigned_issues.dart +++ b/lib/screens/profile/user-profile/assigned_issues.dart @@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_rich_text.dart'; diff --git a/lib/screens/MainScreens/Profile/User_profile/created_issue_page.dart.dart b/lib/screens/profile/user-profile/created_issue_page.dart.dart similarity index 99% rename from lib/screens/MainScreens/Profile/User_profile/created_issue_page.dart.dart rename to lib/screens/profile/user-profile/created_issue_page.dart.dart index 0cf8bd6c..8fc590c5 100644 --- a/lib/screens/MainScreens/Profile/User_profile/created_issue_page.dart.dart +++ b/lib/screens/profile/user-profile/created_issue_page.dart.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_rich_text.dart'; diff --git a/lib/screens/MainScreens/Profile/User_profile/member_profile.dart b/lib/screens/profile/user-profile/member_profile.dart similarity index 77% rename from lib/screens/MainScreens/Profile/User_profile/member_profile.dart rename to lib/screens/profile/user-profile/member_profile.dart index ab086d25..f4fe8ba7 100644 --- a/lib/screens/MainScreens/Profile/User_profile/member_profile.dart +++ b/lib/screens/profile/user-profile/member_profile.dart @@ -13,10 +13,10 @@ import 'package:plane/widgets/loading_widget.dart'; import 'package:plane/widgets/member_logo_widget.dart'; import 'package:plane/widgets/shimmer_effect_widget.dart'; -import '../../../../bottom_sheets/project_select_cover_image.dart'; -import '../../../../provider/profile_provider.dart'; -import '../../../../utils/constants.dart'; -import '../../../../utils/app_theme.dart'; +import '../../../bottom-sheets/project_select_cover_image.dart'; +import '../../../provider/profile_provider.dart'; +import '../../../utils/constants.dart'; +import '../../../utils/app_theme.dart'; class MemberProfile extends ConsumerStatefulWidget { const MemberProfile({required this.userID, super.key}); @@ -191,104 +191,107 @@ class _MemberProfileState extends ConsumerState { ), memberprofileProvider.expanded[index] ? Column( - children: [ - memberprofileProvider.memberProfile['project_data'] - [index][ - memberprofileProvider.projectData[0] - ['key']] == - 0 && - memberprofileProvider - .memberProfile['project_data'] - [index][ - memberprofileProvider.projectData[1] - ['key']] == - 0 - ? Container() - : Padding( - padding: const EdgeInsets.only(bottom: 10), - child: CustomProgressBar.withColorOverride( - width: width, - itemValue: [ - memberprofileProvider.memberProfile[ - 'project_data'][index][ + children: [ + memberprofileProvider.memberProfile['project_data'] + [index][ memberprofileProvider.projectData[0] - ['key']], - memberprofileProvider.memberProfile[ - 'project_data'][index][ + ['key']] == + 0 && + memberprofileProvider + .memberProfile['project_data'] + [index][ memberprofileProvider.projectData[1] - ['key']], - memberprofileProvider.memberProfile[ - 'project_data'][index][ - memberprofileProvider.projectData[2] - ['key']], - memberprofileProvider.memberProfile[ - 'project_data'][index][ - memberprofileProvider.projectData[3] - ['key']], - ], - itemColors: [ - memberprofileProvider.projectData[0] - ['color'], - memberprofileProvider.projectData[1] - ['color'], - memberprofileProvider.projectData[2] - ['color'], - memberprofileProvider.projectData[3] - ['color'], - ]), - ), - ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: - memberprofileProvider.projectData.length, - itemBuilder: (ctx, i) { - return Container( - margin: const EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - margin: const EdgeInsets.only( - left: 30, right: 10), - height: 12, - width: 12, - decoration: BoxDecoration( - color: memberprofileProvider - .projectData[i]['color'], - borderRadius: - BorderRadius.circular(4)), - ), - Container( - margin: const EdgeInsets.only(), - child: CustomText( - memberprofileProvider.projectData[i] - ['name'], - color: themeProvider.themeManager - .placeholderTextColor, - type: FontStyle.Small, - fontWeight: FontWeightt.Regular, + ['key']] == + 0 + ? Container() + : Padding( + padding: const EdgeInsets.only(bottom: 10), + child: CustomProgressBar.withColorOverride( + width: width, + itemValue: [ + memberprofileProvider + .memberProfile['project_data'] + [index][ + memberprofileProvider.projectData[0] + ['key']], + memberprofileProvider + .memberProfile['project_data'] + [index][ + memberprofileProvider.projectData[1] + ['key']], + memberprofileProvider + .memberProfile['project_data'] + [index][ + memberprofileProvider.projectData[2] + ['key']], + memberprofileProvider + .memberProfile['project_data'] + [index][ + memberprofileProvider.projectData[3] + ['key']], + ], + itemColors: [ + memberprofileProvider.projectData[0] + ['color'], + memberprofileProvider.projectData[1] + ['color'], + memberprofileProvider.projectData[2] + ['color'], + memberprofileProvider.projectData[3] + ['color'], + ]), + ), + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: memberprofileProvider.projectData.length, + itemBuilder: (ctx, i) { + return Container( + margin: const EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.only( + left: 30, right: 10), + height: 12, + width: 12, + decoration: BoxDecoration( + color: memberprofileProvider + .projectData[i]['color'], + borderRadius: + BorderRadius.circular(4)), ), - ), - const Spacer(), - Container( - margin: const EdgeInsets.only( - right: 30, + Container( + margin: const EdgeInsets.only(), + child: CustomText( + memberprofileProvider.projectData[i] + ['name'], + color: themeProvider + .themeManager.placeholderTextColor, + type: FontStyle.Small, + fontWeight: FontWeightt.Regular, + ), ), - child: CustomText( - "${memberprofileProvider.memberProfile['project_data'][index][memberprofileProvider.projectData[i]['key']]} Issues", - color: themeProvider - .themeManager.tertiaryTextColor, - type: FontStyle.Small, - fontWeight: FontWeightt.Medium, + const Spacer(), + Container( + margin: const EdgeInsets.only( + right: 30, + ), + child: CustomText( + "${memberprofileProvider.memberProfile['project_data'][index][memberprofileProvider.projectData[i]['key']]} Issues", + color: themeProvider + .themeManager.tertiaryTextColor, + type: FontStyle.Small, + fontWeight: FontWeightt.Medium, + ), ), - ), - ], - ), - ); - }), - ], - ) + ], + ), + ); + }), + ], + ) : Container(), index == memberprofileProvider diff --git a/lib/screens/MainScreens/Profile/User_profile/over_view.dart b/lib/screens/profile/user-profile/over_view.dart similarity index 98% rename from lib/screens/MainScreens/Profile/User_profile/over_view.dart rename to lib/screens/profile/user-profile/over_view.dart index 7f082990..7948763a 100644 --- a/lib/screens/MainScreens/Profile/User_profile/over_view.dart +++ b/lib/screens/profile/user-profile/over_view.dart @@ -6,9 +6,9 @@ import 'package:loading_indicator/loading_indicator.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:plane/config/const.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; +import 'package:plane/screens/project/cycles/cycle-detail/cycle_issues_page.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; +import 'package:plane/screens/project/modules/module-detail/module_issues_page.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; diff --git a/lib/screens/MainScreens/Profile/User_profile/subscribed_issues.dart b/lib/screens/profile/user-profile/subscribed_issues.dart similarity index 99% rename from lib/screens/MainScreens/Profile/User_profile/subscribed_issues.dart rename to lib/screens/profile/user-profile/subscribed_issues.dart index 6df4ac73..5ee3e0f5 100644 --- a/lib/screens/MainScreens/Profile/User_profile/subscribed_issues.dart +++ b/lib/screens/profile/user-profile/subscribed_issues.dart @@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_rich_text.dart'; diff --git a/lib/screens/MainScreens/Profile/User_profile/user_profile.dart b/lib/screens/profile/user-profile/user_profile.dart similarity index 93% rename from lib/screens/MainScreens/Profile/User_profile/user_profile.dart rename to lib/screens/profile/user-profile/user_profile.dart index cdda695e..2ce50fe8 100644 --- a/lib/screens/MainScreens/Profile/User_profile/user_profile.dart +++ b/lib/screens/profile/user-profile/user_profile.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Profile/User_profile/assigned_issues.dart'; -import 'package:plane/screens/MainScreens/Profile/User_profile/created_issue_page.dart.dart'; -import 'package:plane/screens/MainScreens/Profile/User_profile/member_profile.dart'; -import 'package:plane/screens/MainScreens/Profile/User_profile/over_view.dart'; -import 'package:plane/screens/MainScreens/Profile/User_profile/subscribed_issues.dart'; +import 'package:plane/screens/profile/user-profile/assigned_issues.dart'; +import 'package:plane/screens/profile/user-profile/created_issue_page.dart.dart'; +import 'package:plane/screens/profile/user-profile/member_profile.dart'; +import 'package:plane/screens/profile/user-profile/over_view.dart'; +import 'package:plane/screens/profile/user-profile/subscribed_issues.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Profile/WorkpsaceSettings/invite_members.dart b/lib/screens/profile/workpsace-settings/invite_members.dart similarity index 99% rename from lib/screens/MainScreens/Profile/WorkpsaceSettings/invite_members.dart rename to lib/screens/profile/workpsace-settings/invite_members.dart index 2383f9c2..86178de8 100644 --- a/lib/screens/MainScreens/Profile/WorkpsaceSettings/invite_members.dart +++ b/lib/screens/profile/workpsace-settings/invite_members.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/member_status.dart'; +import 'package:plane/bottom-sheets/member_status.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/screens/MainScreens/Profile/WorkpsaceSettings/members.dart b/lib/screens/profile/workpsace-settings/members.dart similarity index 99% rename from lib/screens/MainScreens/Profile/WorkpsaceSettings/members.dart rename to lib/screens/profile/workpsace-settings/members.dart index 877083dd..1bc4d62c 100644 --- a/lib/screens/MainScreens/Profile/WorkpsaceSettings/members.dart +++ b/lib/screens/profile/workpsace-settings/members.dart @@ -2,16 +2,16 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:plane/bottom_sheets/delete_leave_project_sheet.dart'; -import 'package:plane/bottom_sheets/delete_workspace_sheet.dart'; +import 'package:plane/bottom-sheets/delete_leave_project_sheet.dart'; +import 'package:plane/bottom-sheets/delete_workspace_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Profile/User_profile/user_profile.dart'; +import 'package:plane/screens/profile/user-profile/user_profile.dart'; +import 'package:plane/screens/profile/workpsace-settings/invite_members.dart'; import 'package:plane/utils/color_manager.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; -import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/invite_members.dart'; import 'package:plane/utils/constants.dart'; -import 'package:plane/bottom_sheets/member_status.dart'; +import 'package:plane/bottom-sheets/member_status.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/error_state.dart'; diff --git a/lib/screens/MainScreens/Profile/WorkpsaceSettings/workspace_general.dart b/lib/screens/profile/workpsace-settings/workspace_general.dart similarity index 99% rename from lib/screens/MainScreens/Profile/WorkpsaceSettings/workspace_general.dart rename to lib/screens/profile/workpsace-settings/workspace_general.dart index cbad1493..e28875ad 100644 --- a/lib/screens/MainScreens/Profile/WorkpsaceSettings/workspace_general.dart +++ b/lib/screens/profile/workpsace-settings/workspace_general.dart @@ -7,8 +7,8 @@ import 'package:flutter/scheduler.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:image_picker/image_picker.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/company_size_sheet.dart'; -import 'package:plane/bottom_sheets/delete_workspace_sheet.dart'; +import 'package:plane/bottom-sheets/company_size_sheet.dart'; +import 'package:plane/bottom-sheets/delete_workspace_sheet.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart b/lib/screens/project/archived_issues.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart rename to lib/screens/project/archived_issues.dart index aeb14726..55399927 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart +++ b/lib/screens/project/archived_issues.dart @@ -2,10 +2,10 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; -import 'package:plane/bottom_sheets/views_sheet.dart'; +import 'package:plane/bottom-sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom-sheets/views_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/custom_text.dart'; @@ -139,12 +139,12 @@ class _ArchivedIssuesState extends ConsumerState { Container( padding: const EdgeInsets - .only( + .only( left: 15), margin: const EdgeInsets - .only( + .only( bottom: 10), child: Row( @@ -249,7 +249,7 @@ class _ArchivedIssuesState extends ConsumerState { .isEmpty ? Container( margin: const EdgeInsets - .only( + .only( bottom: 10), width: MediaQuery.of( @@ -260,7 +260,7 @@ class _ArchivedIssuesState extends ConsumerState { .themeManager .primaryBackgroundDefaultColor, padding: const EdgeInsets - .only( + .only( top: 15, bottom: @@ -280,7 +280,7 @@ class _ArchivedIssuesState extends ConsumerState { ) : Container( margin: const EdgeInsets - .only( + .only( bottom: 10), ) diff --git a/lib/screens/MainScreens/Projects/create_project_screen.dart b/lib/screens/project/create_project_screen.dart similarity index 99% rename from lib/screens/MainScreens/Projects/create_project_screen.dart rename to lib/screens/project/create_project_screen.dart index 86cdbdcd..6bcb9f04 100644 --- a/lib/screens/MainScreens/Projects/create_project_screen.dart +++ b/lib/screens/project/create_project_screen.dart @@ -5,12 +5,12 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/emoji_sheet.dart'; +import 'package:plane/bottom-sheets/emoji_sheet.dart'; import 'package:plane/config/const.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/custom_button.dart'; -import 'package:plane/bottom_sheets/project_select_cover_image.dart'; +import 'package:plane/bottom-sheets/project_select_cover_image.dart'; import 'package:plane/widgets/loading_widget.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart b/lib/screens/project/cycles/create_cycle.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart rename to lib/screens/project/cycles/create_cycle.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_details_page.dart b/lib/screens/project/cycles/cycle-detail/cycle_details_page.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_details_page.dart rename to lib/screens/project/cycles/cycle-detail/cycle_details_page.dart index 138414ec..1ad501c3 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_details_page.dart +++ b/lib/screens/project/cycles/cycle-detail/cycle_details_page.dart @@ -4,13 +4,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/assignee_sheet.dart'; +import 'package:plane/bottom-sheets/assignee_sheet.dart'; import 'package:plane/models/chart_model.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart'; +import 'package:plane/screens/project/widgets/assignee_widget.dart'; +import 'package:plane/screens/project/widgets/assignees_widget.dart'; +import 'package:plane/screens/project/widgets/progress_chart.dart'; +import 'package:plane/screens/project/widgets/states_widget.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; @@ -61,7 +61,8 @@ class _CycleDetailsPageState extends ConsumerState { const SizedBox(height: 30), progressWidget(ref: ref, chartData: widget.chartData), const SizedBox(height: 30), - assigneesWidget(ref: ref, detailData: cyclesProvider.cyclesDetailsData), + assigneesWidget( + ref: ref, detailData: cyclesProvider.cyclesDetailsData), const SizedBox(height: 30), statesWidget(ref: ref, detailData: cyclesProvider.cyclesDetailsData), const SizedBox(height: 30), @@ -73,7 +74,6 @@ class _CycleDetailsPageState extends ConsumerState { } } - Widget dateWidget() { final cyclesProvider = ref.watch(ProviderList.cyclesProvider); final themeProvider = ref.watch(ProviderList.themeProvider); diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart b/lib/screens/project/cycles/cycle-detail/cycle_issues_page.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart rename to lib/screens/project/cycles/cycle-detail/cycle_issues_page.dart index d1b111dc..c8478321 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart +++ b/lib/screens/project/cycles/cycle-detail/cycle_issues_page.dart @@ -5,26 +5,26 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; -import 'package:plane/bottom_sheets/type_sheet.dart'; -import 'package:plane/bottom_sheets/views_sheet.dart'; +import 'package:plane/bottom-sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom-sheets/type_sheet.dart'; +import 'package:plane/bottom-sheets/views_sheet.dart'; import 'package:plane/kanban/custom/board.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/chart_model.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_details_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/calender_view.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart'; +import 'package:plane/screens/project/cycles/cycle-detail/cycle_details_page.dart'; +import 'package:plane/screens/project/issue-layouts/calender_view.dart'; +import 'package:plane/screens/project/issue-layouts/spreadsheet_view.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/empty.dart'; -import '../../../../../../bottom_sheets/select_cycle_sheet.dart'; -import '../../Issues/issue_detail.dart'; +import '../../../../../bottom-sheets/select_cycle_sheet.dart'; class CycleDetail extends ConsumerStatefulWidget { const CycleDetail( @@ -126,7 +126,8 @@ class _CycleDetailState extends ConsumerState { Future getChartData(Map data) async { data.forEach((key, value) { - chartData.add(ChartData(DateTime.parse(key), value != null ? value.toDouble() : 0)); + chartData.add( + ChartData(DateTime.parse(key), value != null ? value.toDouble() : 0)); }); } diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/cycle_active_card.dart b/lib/screens/project/cycles/cycle_active_card.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Cycles/cycle_active_card.dart rename to lib/screens/project/cycles/cycle_active_card.dart index 5f2969ad..99da1a71 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/cycle_active_card.dart +++ b/lib/screens/project/cycles/cycle_active_card.dart @@ -7,7 +7,7 @@ import 'package:plane/models/chart_model.dart'; import 'package:plane/provider/cycles_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; +import 'package:plane/screens/project/cycles/cycle-detail/cycle_issues_page.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/extensions/list_extensions.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart b/lib/screens/project/cycles/project_details_cycles.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart rename to lib/screens/project/cycles/project_details_cycles.dart index 7fc7bd30..da375537 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart +++ b/lib/screens/project/cycles/project_details_cycles.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/cycle_active_card.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; +import 'package:plane/screens/project/cycles/cycle-detail/cycle_issues_page.dart'; +import 'package:plane/screens/project/cycles/cycle_active_card.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/calender_view.dart b/lib/screens/project/issue-layouts/calender_view.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/calender_view.dart rename to lib/screens/project/issue-layouts/calender_view.dart index 10772c17..3c122642 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/calender_view.dart +++ b/lib/screens/project/issue-layouts/calender_view.dart @@ -1,13 +1,12 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; -import 'package:plane/bottom_sheets/type_sheet.dart'; +import 'package:plane/bottom-sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom-sheets/type_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; @@ -15,8 +14,6 @@ import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/square_avatar_widget.dart'; import 'package:table_calendar/table_calendar.dart'; -import 'Issues/issue_detail.dart'; - class CalendarView extends ConsumerStatefulWidget { const CalendarView({Key? key}) : super(key: key); diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/issue_layout.dart b/lib/screens/project/issue-layouts/issue_layout.dart similarity index 77% rename from lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/issue_layout.dart rename to lib/screens/project/issue-layouts/issue_layout.dart index 5b82c8f1..e8e75fc9 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/issue_layout.dart +++ b/lib/screens/project/issue-layouts/issue_layout.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issue%20Layouts/Kanban%20Layout/kanban_root.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issue%20Layouts/List%20Layout/list_root.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/calender_view.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart'; +import 'package:plane/screens/project/issue-layouts/calender_view.dart'; +import 'package:plane/screens/project/issue-layouts/kanban-layout/kanban_root.dart'; +import 'package:plane/screens/project/issue-layouts/list-layout/list_root.dart'; +import 'package:plane/screens/project/issue-layouts/spreadsheet_view.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/empty.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/Kanban Layout/kanban_root.dart b/lib/screens/project/issue-layouts/kanban-layout/kanban_root.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/Kanban Layout/kanban_root.dart rename to lib/screens/project/issue-layouts/kanban-layout/kanban_root.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart b/lib/screens/project/issue-layouts/list-layout/list_root.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart rename to lib/screens/project/issue-layouts/list-layout/list_root.dart index b015d7c9..422afadd 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Issue Layouts/List Layout/list_root.dart +++ b/lib/screens/project/issue-layouts/list-layout/list_root.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart b/lib/screens/project/issue-layouts/spreadsheet_view.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart rename to lib/screens/project/issue-layouts/spreadsheet_view.dart index 75be7344..f75c4796 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart +++ b/lib/screens/project/issue-layouts/spreadsheet_view.dart @@ -2,13 +2,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/square_avatar_widget.dart'; -import 'Issues/issue_detail.dart'; - class SpreadSheetView extends ConsumerStatefulWidget { const SpreadSheetView({super.key, required this.issueCategory}); final IssueCategory issueCategory; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart b/lib/screens/project/issues/create_issue.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart rename to lib/screens/project/issues/create_issue.dart index 993434eb..a5a1bf89 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart +++ b/lib/screens/project/issues/create_issue.dart @@ -7,19 +7,19 @@ import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/issues_list_sheet.dart'; -import 'package:plane/bottom_sheets/selectProjectSheet.dart'; -import 'package:plane/bottom_sheets/select_estimate.dart'; -import 'package:plane/bottom_sheets/select_issue_labels.dart'; -import 'package:plane/bottom_sheets/select_priority.dart'; -import 'package:plane/bottom_sheets/select_project_members.dart'; -import 'package:plane/bottom_sheets/select_states.dart'; +import 'package:plane/bottom-sheets/issues_list_sheet.dart'; +import 'package:plane/bottom-sheets/selectProjectSheet.dart'; +import 'package:plane/bottom-sheets/select_estimate.dart'; +import 'package:plane/bottom-sheets/select_issue_labels.dart'; +import 'package:plane/bottom-sheets/select_priority.dart'; +import 'package:plane/bottom-sheets/select_project_members.dart'; +import 'package:plane/bottom-sheets/select_states.dart'; import 'package:plane/config/config_variables.dart'; import 'package:plane/config/const.dart'; import 'package:plane/mixins/widget_state_mixin.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/selected_label_widget.dart'; +import 'package:plane/screens/project/issues/widgets/selected_label_widget.dart'; import 'package:plane/utils/color_manager.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart b/lib/screens/project/issues/issue_detail.dart similarity index 96% rename from lib/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart rename to lib/screens/project/issues/issue_detail.dart index 24ab7597..b61b39a9 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart +++ b/lib/screens/project/issues/issue_detail.dart @@ -5,10 +5,10 @@ import 'package:plane/provider/issues_provider.dart'; import 'package:plane/provider/my_issues_provider.dart'; import 'package:plane/utils/enums.dart'; -import '../../../../../provider/cycles_provider.dart'; -import '../../../../../provider/modules_provider.dart'; -import '../../../../../provider/provider_list.dart'; -import '../../../../../utils/editor.dart'; +import '../../../../provider/cycles_provider.dart'; +import '../../../../provider/modules_provider.dart'; +import '../../../../provider/provider_list.dart'; +import '../../../../utils/editor.dart'; enum PreviousScreen { myIssues, diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issues/issues_tab.dart b/lib/screens/project/issues/issues_tab.dart similarity index 91% rename from lib/screens/MainScreens/Projects/ProjectDetail/Issues/issues_tab.dart rename to lib/screens/project/issues/issues_tab.dart index 6a6af532..76058a4a 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Issues/issues_tab.dart +++ b/lib/screens/project/issues/issues_tab.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issue%20Layouts/issue_layout.dart'; +import 'package:plane/screens/project/issue-layouts/issue_layout.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/loading_widget.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/selected_label_widget.dart b/lib/screens/project/issues/widgets/selected_label_widget.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/selected_label_widget.dart rename to lib/screens/project/issues/widgets/selected_label_widget.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart b/lib/screens/project/models/project_detail_models.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart rename to lib/screens/project/models/project_detail_models.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart b/lib/screens/project/modules/create_module.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart rename to lib/screens/project/modules/create_module.dart index e186f2be..268b8d2b 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart +++ b/lib/screens/project/modules/create_module.dart @@ -6,9 +6,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:intl/intl.dart'; -import 'package:plane/bottom_sheets/assignee_sheet.dart'; -import 'package:plane/bottom_sheets/lead_sheet.dart'; -import 'package:plane/bottom_sheets/status_sheet.dart'; +import 'package:plane/bottom-sheets/assignee_sheet.dart'; +import 'package:plane/bottom-sheets/lead_sheet.dart'; +import 'package:plane/bottom-sheets/status_sheet.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/widgets/custom_button.dart'; import 'package:plane/widgets/loading_widget.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_detail_page.dart b/lib/screens/project/modules/module-detail/module_detail_page.dart similarity index 97% rename from lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_detail_page.dart rename to lib/screens/project/modules/module-detail/module_detail_page.dart index 710d8783..6ca73b03 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_detail_page.dart +++ b/lib/screens/project/modules/module-detail/module_detail_page.dart @@ -4,14 +4,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/assignee_sheet.dart'; +import 'package:plane/bottom-sheets/assignee_sheet.dart'; import 'package:plane/models/chart_model.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/links_widget.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart'; +import 'package:plane/screens/project/widgets/assignee_widget.dart'; +import 'package:plane/screens/project/widgets/assignees_widget.dart'; +import 'package:plane/screens/project/widgets/links_widget.dart'; +import 'package:plane/screens/project/widgets/progress_chart.dart'; +import 'package:plane/screens/project/widgets/states_widget.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; @@ -62,7 +62,9 @@ class _ModuleDetailsPageState extends ConsumerState { const SizedBox(height: 30), progressWidget(ref: ref, chartData: widget.chartData), const SizedBox(height: 30), - assigneesWidget(ref: ref, detailData: modulesProvider.moduleDetailsData['distribution']), + assigneesWidget( + ref: ref, + detailData: modulesProvider.moduleDetailsData['distribution']), const SizedBox(height: 30), statesWidget(ref: ref, detailData: modulesProvider.moduleDetailsData), const SizedBox(height: 30), @@ -273,7 +275,7 @@ class _ModuleDetailsPageState extends ConsumerState { return; } if (date.isAfter(startDate!)) { - modulesProvider.updateModules( + modulesProvider.updateModules( disableLoading: true, slug: ref .read(ProviderList.workspaceProvider) @@ -286,9 +288,8 @@ class _ModuleDetailsPageState extends ConsumerState { data: { 'end_date': DateFormat('yyyy-MM-dd').format(date) }, - ref: ref - ); - modulesProvider.changeTabIndex(1); + ref: ref); + modulesProvider.changeTabIndex(1); } else { CustomToast.showToast(context, message: 'Start date cannot be after end date ', diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart b/lib/screens/project/modules/module-detail/module_issues_page.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart rename to lib/screens/project/modules/module-detail/module_issues_page.dart index 58ada121..d4d0d3f4 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart +++ b/lib/screens/project/modules/module-detail/module_issues_page.dart @@ -5,26 +5,26 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; -import 'package:plane/bottom_sheets/type_sheet.dart'; -import 'package:plane/bottom_sheets/views_sheet.dart'; +import 'package:plane/bottom-sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom-sheets/type_sheet.dart'; +import 'package:plane/bottom-sheets/views_sheet.dart'; import 'package:plane/kanban/custom/board.dart'; import 'package:plane/kanban/models/inputs.dart'; import 'package:plane/models/chart_model.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_detail_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/calender_view.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/spreadsheet_view.dart'; +import 'package:plane/screens/project/issue-layouts/calender_view.dart'; +import 'package:plane/screens/project/issue-layouts/spreadsheet_view.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; +import 'package:plane/screens/project/modules/module-detail/module_detail_page.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/empty.dart'; -import '../../../../../../bottom_sheets/select_cycle_sheet.dart'; -import '../../Issues/issue_detail.dart'; +import '../../../../../bottom-sheets/select_cycle_sheet.dart'; class ModuleDetail extends ConsumerStatefulWidget { const ModuleDetail( @@ -125,7 +125,8 @@ class _ModuleDetailState extends ConsumerState { Future getChartData(Map data) async { data.forEach((key, value) { - chartData.add(ChartData(DateTime.parse(key), value != null ? value.toDouble() : 0.0)); + chartData.add(ChartData( + DateTime.parse(key), value != null ? value.toDouble() : 0.0)); }); } diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_screen.dart b/lib/screens/project/modules/module_screen.dart similarity index 97% rename from lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_screen.dart rename to lib/screens/project/modules/module_screen.dart index e1ba440c..8446c5bf 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_screen.dart +++ b/lib/screens/project/modules/module_screen.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/simple_module_card.dart'; +import 'package:plane/screens/project/modules/widgets/simple_module_card.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/empty.dart'; import 'package:plane/widgets/loading_widget.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_card.dart b/lib/screens/project/modules/widgets/module_card.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_card.dart rename to lib/screens/project/modules/widgets/module_card.dart index a8835190..8edfe04c 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/module_card.dart +++ b/lib/screens/project/modules/widgets/module_card.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; -import 'package:plane/bottom_sheets/delete_module_sheet.dart'; - +import 'package:plane/bottom-sheets/delete_module_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; +import 'package:plane/screens/project/modules/module-detail/module_issues_page.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/utils/constants.dart'; import '/utils/enums.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/simple_module_card.dart b/lib/screens/project/modules/widgets/simple_module_card.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/Modules/simple_module_card.dart rename to lib/screens/project/modules/widgets/simple_module_card.dart index 634e08d6..918f3db0 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Modules/simple_module_card.dart +++ b/lib/screens/project/modules/widgets/simple_module_card.dart @@ -2,13 +2,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:lucide_icons/lucide_icons.dart'; -import 'package:plane/bottom_sheets/delete_cycle_sheet.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/ModuleDetail/module_issues_page.dart'; +import 'package:plane/bottom-sheets/delete_cycle_sheet.dart'; +import 'package:plane/screens/project/modules/module-detail/module_issues_page.dart'; import 'package:plane/utils/string_manager.dart'; import '/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/widgets/custom_text.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/CycleDetail/cycle_issues_page.dart'; class SimpleModuleCard extends ConsumerStatefulWidget { const SimpleModuleCard({ diff --git a/lib/screens/MainScreens/Projects/create_page_screen.dart b/lib/screens/project/pages/create_page_screen.dart similarity index 100% rename from lib/screens/MainScreens/Projects/create_page_screen.dart rename to lib/screens/project/pages/create_page_screen.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_detail.dart b/lib/screens/project/pages/page_detail.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_detail.dart rename to lib/screens/project/pages/page_detail.dart index f2f37ac5..9d210c53 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_detail.dart +++ b/lib/screens/project/pages/page_detail.dart @@ -4,8 +4,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/block_sheet.dart'; -import 'package:plane/bottom_sheets/label_sheet.dart'; +import 'package:plane/bottom-sheets/block_sheet.dart'; +import 'package:plane/bottom-sheets/label_sheet.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_screen.dart b/lib/screens/project/pages/page_screen.dart similarity index 94% rename from lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_screen.dart rename to lib/screens/project/pages/page_screen.dart index 22992c5b..12634463 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_screen.dart +++ b/lib/screens/project/pages/page_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Pages/page_card.dart'; +import 'package:plane/screens/project/pages/widgets/page_card.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/loading_widget.dart'; import 'package:plane/widgets/empty.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_block_card.dart b/lib/screens/project/pages/widgets/page_block_card.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_block_card.dart rename to lib/screens/project/pages/widgets/page_block_card.dart index dca3a02d..2828460f 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_block_card.dart +++ b/lib/screens/project/pages/widgets/page_block_card.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:plane/bottom_sheets/block_sheet.dart'; +import 'package:plane/bottom-sheets/block_sheet.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_card.dart b/lib/screens/project/pages/widgets/page_card.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_card.dart rename to lib/screens/project/pages/widgets/page_card.dart index 389a7060..901ce059 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Pages/page_card.dart +++ b/lib/screens/project/pages/widgets/page_card.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:plane/bottom_sheets/delete_cycle_sheet.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Pages/page_detail.dart'; +import 'package:plane/bottom-sheets/delete_cycle_sheet.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/project/pages/page_detail.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart b/lib/screens/project/project_detail.dart similarity index 90% rename from lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart rename to lib/screens/project/project_detail.dart index 40e3d2e2..a6629047 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/project_detail.dart +++ b/lib/screens/project/project_detail.dart @@ -2,11 +2,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Views/views.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart'; +import 'package:plane/screens/project/cycles/project_details_cycles.dart'; +import 'package:plane/screens/project/views/views.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/empty.dart'; +import 'widgets/floating_action_button.dart'; import 'widgets/project_detail_appbar.dart'; import 'widgets/project_detail_root.dart'; @@ -100,10 +100,7 @@ Widget view(WidgetRef ref) { padding: const EdgeInsets.only(left: 20, right: 20, top: 15), child: const Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Views() - ], + children: [Views()], ), ); } - diff --git a/lib/screens/MainScreens/Projects/project_screen.dart b/lib/screens/project/project_screen.dart similarity index 99% rename from lib/screens/MainScreens/Projects/project_screen.dart rename to lib/screens/project/project_screen.dart index 7eb2abaf..72ad6aa5 100644 --- a/lib/screens/MainScreens/Projects/project_screen.dart +++ b/lib/screens/project/project_screen.dart @@ -4,11 +4,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; -import 'package:plane/bottom_sheets/global_search_sheet.dart'; +import 'package:plane/bottom-sheets/global_search_sheet.dart'; import 'package:plane/provider/projects_provider.dart'; import 'package:plane/provider/theme_provider.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/project_detail.dart'; -import 'package:plane/screens/MainScreens/Projects/create_project_screen.dart'; +import 'package:plane/screens/project/create_project_screen.dart'; +import 'package:plane/screens/project/project_detail.dart'; import 'package:plane/utils/color_manager.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/automations_page.dart b/lib/screens/project/settings/automations_page.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Settings/automations_page.dart rename to lib/screens/project/settings/automations_page.dart index 92338021..d1f3f61a 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/automations_page.dart +++ b/lib/screens/project/settings/automations_page.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:plane/bottom_sheets/select_automation_state.dart'; -import 'package:plane/bottom_sheets/select_month.dart'; +import 'package:plane/bottom-sheets/select_automation_state.dart'; +import 'package:plane/bottom-sheets/select_month.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/control_page.dart b/lib/screens/project/settings/control_page.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Settings/control_page.dart rename to lib/screens/project/settings/control_page.dart index 8b7f5287..3841f79e 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/control_page.dart +++ b/lib/screens/project/settings/control_page.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/project_lead_assignee_sheet.dart'; +import 'package:plane/bottom-sheets/project_lead_assignee_sheet.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart b/lib/screens/project/settings/create_label.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart rename to lib/screens/project/settings/create_label.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/estimates_page.dart b/lib/screens/project/settings/estimates_page.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Settings/estimates_page.dart rename to lib/screens/project/settings/estimates_page.dart index 9baf129d..d4768cbf 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/estimates_page.dart +++ b/lib/screens/project/settings/estimates_page.dart @@ -3,8 +3,8 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:plane/bottom_sheets/create_estimate.dart'; -import 'package:plane/bottom_sheets/delete_estimate_sheet.dart'; +import 'package:plane/bottom-sheets/create_estimate.dart'; +import 'package:plane/bottom-sheets/delete_estimate_sheet.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/widgets/loading_widget.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/features_page.dart b/lib/screens/project/settings/features_page.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/Settings/features_page.dart rename to lib/screens/project/settings/features_page.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/general_page.dart b/lib/screens/project/settings/general_page.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Settings/general_page.dart rename to lib/screens/project/settings/general_page.dart index e350e729..94ba7d4a 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/general_page.dart +++ b/lib/screens/project/settings/general_page.dart @@ -4,9 +4,9 @@ import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/delete_leave_project_sheet.dart'; -import 'package:plane/bottom_sheets/emoji_sheet.dart'; -import 'package:plane/bottom_sheets/project_select_cover_image.dart'; +import 'package:plane/bottom-sheets/delete_leave_project_sheet.dart'; +import 'package:plane/bottom-sheets/emoji_sheet.dart'; +import 'package:plane/bottom-sheets/project_select_cover_image.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/integrations_page.dart b/lib/screens/project/settings/integrations_page.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/Settings/integrations_page.dart rename to lib/screens/project/settings/integrations_page.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/lables_page.dart b/lib/screens/project/settings/lables_page.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Settings/lables_page.dart rename to lib/screens/project/settings/lables_page.dart index d91f7009..07bae03b 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/lables_page.dart +++ b/lib/screens/project/settings/lables_page.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/delete_labels_sheet.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart'; +import 'package:plane/bottom-sheets/delete_labels_sheet.dart'; +import 'package:plane/screens/project/settings/create_label.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart b/lib/screens/project/settings/states_pages.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart rename to lib/screens/project/settings/states_pages.dart index 6813323e..613c5aaa 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart +++ b/lib/screens/project/settings/states_pages.dart @@ -1,19 +1,16 @@ // ignore_for_file: use_build_context_synchronously - import 'dart:math'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:loading_indicator/loading_indicator.dart'; -import 'package:plane/bottom_sheets/delete_state_sheet.dart'; +import 'package:plane/bottom-sheets/delete_state_sheet.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; import 'package:plane/widgets/custom_button.dart'; - import 'package:plane/widgets/custom_text.dart'; class StatesPage extends ConsumerStatefulWidget { diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Views/views.dart b/lib/screens/project/views/views.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/Views/views.dart rename to lib/screens/project/views/views.dart index f6285497..808fe7b1 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Views/views.dart +++ b/lib/screens/project/views/views.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:lucide_icons/lucide_icons.dart'; -import 'package:plane/bottom_sheets/delete_cycle_sheet.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart'; +import 'package:plane/bottom-sheets/delete_cycle_sheet.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/project/views/views_detail.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/empty.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart b/lib/screens/project/views/views_detail.dart similarity index 98% rename from lib/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart rename to lib/screens/project/views/views_detail.dart index 128dc9fd..a74cca81 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/Views/views_detail.dart +++ b/lib/screens/project/views/views_detail.dart @@ -5,17 +5,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/models/issues.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; import 'package:plane/utils/custom_toast.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'package:plane/widgets/loading_widget.dart'; - -import '../../../../../bottom_sheets/filters/filter_sheet.dart'; -import '../../../../../bottom_sheets/type_sheet.dart'; -import '../../../../../bottom_sheets/views_sheet.dart'; +import '../../../../../bottom-sheets/filters/filter_sheet.dart'; +import '../../../../../bottom-sheets/type_sheet.dart'; +import '../../../../../bottom-sheets/views_sheet.dart'; import '../../../../../utils/constants.dart'; import '../../../../../utils/enums.dart'; import '../../../../../widgets/custom_text.dart'; -import '../Issues/CreateIssue/create_issue.dart'; class ViewsDetail extends ConsumerStatefulWidget { const ViewsDetail( diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart b/lib/screens/project/widgets/assignee_widget.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignee_widget.dart rename to lib/screens/project/widgets/assignee_widget.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart b/lib/screens/project/widgets/assignees_widget.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/assignees_widget.dart rename to lib/screens/project/widgets/assignees_widget.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart b/lib/screens/project/widgets/floating_action_button.dart similarity index 95% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart rename to lib/screens/project/widgets/floating_action_button.dart index 198bff12..ea458646 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/floating_action_button.dart +++ b/lib/screens/project/widgets/floating_action_button.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart'; import 'package:plane/screens/create_view_screen.dart'; +import 'package:plane/screens/project/cycles/create_cycle.dart'; +import 'package:plane/screens/project/modules/create_module.dart'; import 'package:plane/utils/enums.dart'; // ignore: non_constant_identifier_names diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/links_widget.dart b/lib/screens/project/widgets/links_widget.dart similarity index 99% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/links_widget.dart rename to lib/screens/project/widgets/links_widget.dart index 3203a694..617dcd34 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/links_widget.dart +++ b/lib/screens/project/widgets/links_widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/add_link_sheet.dart'; +import 'package:plane/bottom-sheets/add_link_sheet.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart b/lib/screens/project/widgets/progress_chart.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/progress_chart.dart rename to lib/screens/project/widgets/progress_chart.dart diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart b/lib/screens/project/widgets/project_detail_appbar.dart similarity index 96% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart rename to lib/screens/project/widgets/project_detail_appbar.dart index 8bac38b7..6f2143ed 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_appbar.dart +++ b/lib/screens/project/widgets/project_detail_appbar.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/archived_issues.dart'; +import 'package:plane/screens/project/archived_issues.dart'; import 'package:plane/screens/settings_screen.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart b/lib/screens/project/widgets/project_detail_bottom_actions.dart similarity index 96% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart rename to lib/screens/project/widgets/project_detail_bottom_actions.dart index eee77413..28f3d7b3 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart +++ b/lib/screens/project/widgets/project_detail_bottom_actions.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/filters/filter_sheet.dart'; -import 'package:plane/bottom_sheets/page_filter_sheet.dart'; -import 'package:plane/bottom_sheets/type_sheet.dart'; -import 'package:plane/bottom_sheets/views_sheet.dart'; +import 'package:plane/bottom-sheets/filters/filter_sheet.dart'; +import 'package:plane/bottom-sheets/page_filter_sheet.dart'; +import 'package:plane/bottom-sheets/type_sheet.dart'; +import 'package:plane/bottom-sheets/views_sheet.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/create_page_screen.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/pages/create_page_screen.dart'; import 'package:plane/utils/bottom_sheet.helper.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; @@ -55,7 +55,8 @@ class _PDBottomActionsState extends ConsumerState { child: InkWell( onTap: () { issueProvider.createIssuedata['state'] = - statesProvider.projectStates.keys.first; + statesProvider + .projectStates.keys.first; Navigator.of(context).push( MaterialPageRoute( diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart b/lib/screens/project/widgets/project_detail_root.dart similarity index 83% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart rename to lib/screens/project/widgets/project_detail_root.dart index f7276636..60f3a6c7 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_root.dart +++ b/lib/screens/project/widgets/project_detail_root.dart @@ -3,13 +3,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/project_details_cycles.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/issues_tab.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/module_screen.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Views/views.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_bottom_actions.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart'; +import 'package:plane/screens/project/cycles/project_details_cycles.dart'; +import 'package:plane/screens/project/issues/issues_tab.dart'; +import 'package:plane/screens/project/models/project_detail_models.dart'; +import 'package:plane/screens/project/modules/module_screen.dart'; +import 'package:plane/screens/project/views/views.dart'; +import 'package:plane/screens/project/widgets/project_detail_bottom_actions.dart'; +import 'package:plane/screens/project/widgets/project_detail_tabs.dart'; + import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/error_state.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart b/lib/screens/project/widgets/project_detail_tabs.dart similarity index 96% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart rename to lib/screens/project/widgets/project_detail_tabs.dart index baa0209f..7b3678c2 100644 --- a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/project_detail_tabs.dart +++ b/lib/screens/project/widgets/project_detail_tabs.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/models/project_detail_models.dart'; +import 'package:plane/screens/project/models/project_detail_models.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart b/lib/screens/project/widgets/states_widget.dart similarity index 100% rename from lib/screens/MainScreens/Projects/ProjectDetail/widgets/states_widget.dart rename to lib/screens/project/widgets/states_widget.dart diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index f5940583..c8cfcf61 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -1,23 +1,23 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:plane/bottom_sheets/create_estimate.dart'; -import 'package:plane/bottom_sheets/project_invite_memebers_sheet.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/automations_page.dart'; +import 'package:plane/bottom-sheets/create_estimate.dart'; +import 'package:plane/bottom-sheets/project_invite_memebers_sheet.dart'; +import 'package:plane/screens/profile/workpsace-settings/members.dart'; +import 'package:plane/screens/project/settings/control_page.dart'; +import 'package:plane/screens/project/settings/create_label.dart'; +import 'package:plane/screens/project/settings/estimates_page.dart'; +import 'package:plane/screens/project/settings/features_page.dart'; +import 'package:plane/screens/project/settings/general_page.dart'; +import 'package:plane/screens/project/settings/lables_page.dart'; +import 'package:plane/screens/project/settings/states_pages.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/control_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/estimates_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/features_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/general_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/integrations_page.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/lables_page.dart'; -import 'package:plane/screens/MainScreens/Profile/WorkpsaceSettings/members.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/states_pages.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/widgets/custom_text.dart'; import 'package:plane/widgets/loading_widget.dart'; -import 'MainScreens/Projects/ProjectDetail/Settings/create_label.dart'; +import 'project/settings/integrations_page.dart'; + class SettingScreen extends ConsumerStatefulWidget { const SettingScreen({super.key}); diff --git a/lib/screens/Theming/custom_theme.dart b/lib/screens/themes/custom_theme.dart similarity index 100% rename from lib/screens/Theming/custom_theme.dart rename to lib/screens/themes/custom_theme.dart diff --git a/lib/screens/Theming/prefrences.dart b/lib/screens/themes/prefrences.dart similarity index 99% rename from lib/screens/Theming/prefrences.dart rename to lib/screens/themes/prefrences.dart index c1a10ef8..a2bf4474 100644 --- a/lib/screens/Theming/prefrences.dart +++ b/lib/screens/themes/prefrences.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/screens/Theming/custom_theme.dart'; +import 'package:plane/screens/themes/custom_theme.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart'; diff --git a/lib/screens/unused_screens/issue_detail_unused.dart b/lib/screens/unused-screens/issue_detail_unused.dart similarity index 99% rename from lib/screens/unused_screens/issue_detail_unused.dart rename to lib/screens/unused-screens/issue_detail_unused.dart index 6bd46a9a..58e0a631 100644 --- a/lib/screens/unused_screens/issue_detail_unused.dart +++ b/lib/screens/unused-screens/issue_detail_unused.dart @@ -5,16 +5,16 @@ // import 'package:flutter_svg/svg.dart'; // import 'package:intl/intl.dart'; // import 'package:loading_indicator/loading_indicator.dart'; -// import 'package:plane/bottom_sheets/add_attachment_sheet.dart'; -// import 'package:plane/bottom_sheets/add_link_sheet.dart'; -// import 'package:plane/bottom_sheets/issue_detail_cycles_sheet.dart'; -// import 'package:plane/bottom_sheets/issue_detail_modules_list.dart'; -// import 'package:plane/bottom_sheets/issues_list_sheet.dart'; -// import 'package:plane/bottom_sheets/select_estimate.dart'; -// import 'package:plane/bottom_sheets/select_issue_labels.dart'; -// import 'package:plane/bottom_sheets/select_priority.dart'; -// import 'package:plane/bottom_sheets/select_project_members.dart'; -// import 'package:plane/bottom_sheets/select_states.dart'; +// import 'package:plane/bottom-sheets/add_attachment_sheet.dart'; +// import 'package:plane/bottom-sheets/add_link_sheet.dart'; +// import 'package:plane/bottom-sheets/issue_detail_cycles_sheet.dart'; +// import 'package:plane/bottom-sheets/issue_detail_modules_list.dart'; +// import 'package:plane/bottom-sheets/issues_list_sheet.dart'; +// import 'package:plane/bottom-sheets/select_estimate.dart'; +// import 'package:plane/bottom-sheets/select_issue_labels.dart'; +// import 'package:plane/bottom-sheets/select_priority.dart'; +// import 'package:plane/bottom-sheets/select_project_members.dart'; +// import 'package:plane/bottom-sheets/select_states.dart'; // import 'package:plane/provider/theme_provider.dart'; // import 'package:plane/utils/color_manager.dart'; // import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/services/dio_service.dart b/lib/services/dio_service.dart index 9a33e26a..e48e6b30 100644 --- a/lib/services/dio_service.dart +++ b/lib/services/dio_service.dart @@ -6,7 +6,7 @@ import 'dart:io'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:plane/config/const.dart'; -import 'package:plane/screens/on_boarding/on_boarding_screen.dart'; +import 'package:plane/screens/onboarding/on_boarding_screen.dart'; import 'package:plane/services/shared_preference_service.dart'; import 'package:plane/utils/enums.dart'; import 'package:retry/retry.dart'; diff --git a/lib/utils/editor.dart b/lib/utils/editor.dart index 93330a20..21cf38fb 100644 --- a/lib/utils/editor.dart +++ b/lib/utils/editor.dart @@ -10,12 +10,11 @@ import 'package:loading_indicator/loading_indicator.dart'; import 'package:plane/config/config_variables.dart'; import 'package:plane/provider/issues_provider.dart'; import 'package:plane/provider/provider_list.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_app_bar.dart'; import 'dart:developer'; -import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; - class EDITOR extends ConsumerStatefulWidget { const EDITOR( {required this.url, diff --git a/lib/utils/issues_filter/group_by_issues.dart b/lib/utils/issues_filter/group_by_issues.dart index e23b7a75..96674de8 100644 --- a/lib/utils/issues_filter/group_by_issues.dart +++ b/lib/utils/issues_filter/group_by_issues.dart @@ -1,6 +1,4 @@ -import 'dart:developer'; - -import 'package:plane/models/Project/State/states_model.dart'; +import 'package:plane/models/project/state/state_model.dart'; import 'package:plane/utils/enums.dart'; class IssuesGroupBYHelper { @@ -13,9 +11,9 @@ class IssuesGroupBYHelper { ]; static Map> _groupByState( - List issues, Map states) { + List issues, Map states) { Map> groupedIssues = {}; - Map> stateGroups = {}; + Map> stateGroups = {}; for (final state in defaultStateGroups) { stateGroups[state] = states.values.where((e) => e.group == state).toList(); stateGroups[state]! diff --git a/lib/widgets/cycle_card_widget.dart b/lib/widgets/cycle_card_widget.dart index f58a0bfd..7e25115b 100644 --- a/lib/widgets/cycle_card_widget.dart +++ b/lib/widgets/cycle_card_widget.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:lucide_icons/lucide_icons.dart'; -import 'package:plane/bottom_sheets/delete_cycle_sheet.dart'; +import 'package:plane/bottom-sheets/delete_cycle_sheet.dart'; import 'package:plane/provider/cycles_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; diff --git a/lib/widgets/empty.dart b/lib/widgets/empty.dart index 2512214e..8eb3fda8 100644 --- a/lib/widgets/empty.dart +++ b/lib/widgets/empty.dart @@ -1,15 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:plane/bottom_sheets/issues_list_sheet.dart'; +import 'package:plane/bottom-sheets/issues_list_sheet.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/theme_provider.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Cycles/create_cycle.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Issues/CreateIssue/create_issue.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Modules/create_module.dart'; -import 'package:plane/screens/MainScreens/Projects/ProjectDetail/Settings/create_label.dart'; -import 'package:plane/screens/MainScreens/Projects/create_page_screen.dart'; -import 'package:plane/screens/MainScreens/Projects/create_project_screen.dart'; +import 'package:plane/screens/project/create_project_screen.dart'; +import 'package:plane/screens/project/cycles/create_cycle.dart'; +import 'package:plane/screens/project/issues/create_issue.dart'; +import 'package:plane/screens/project/modules/create_module.dart'; +import 'package:plane/screens/project/pages/create_page_screen.dart'; +import 'package:plane/screens/project/settings/create_label.dart'; import 'package:plane/screens/create_view_screen.dart'; import 'package:plane/utils/constants.dart'; import 'package:plane/utils/custom_toast.dart'; diff --git a/lib/widgets/issue_card_widget.dart b/lib/widgets/issue_card_widget.dart index 29da5f04..5312328f 100644 --- a/lib/widgets/issue_card_widget.dart +++ b/lib/widgets/issue_card_widget.dart @@ -4,11 +4,10 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:intl/intl.dart'; import 'package:plane/config/const.dart'; import 'package:plane/provider/provider_list.dart'; -import 'package:plane/utils/constants.dart'; +import 'package:plane/screens/project/issues/issue_detail.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/utils/extensions/string_extensions.dart'; import 'package:plane/widgets/square_avatar_widget.dart'; -import '../screens/MainScreens/Projects/ProjectDetail/Issues/issue_detail.dart'; import 'custom_rich_text.dart'; import 'custom_text.dart'; diff --git a/test/providers/dashboard/dash_board_screen_test.dart b/test/providers/dashboard/dash_board_screen_test.dart index be0323ed..3205289a 100644 --- a/test/providers/dashboard/dash_board_screen_test.dart +++ b/test/providers/dashboard/dash_board_screen_test.dart @@ -4,8 +4,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; -import 'package:plane/bottom_sheets/global_search_sheet.dart'; -import 'package:plane/bottom_sheets/select_workspace.dart'; +import 'package:plane/bottom-sheets/global_search_sheet.dart'; +import 'package:plane/bottom-sheets/select_workspace.dart'; import 'package:plane/models/user_profile_model.dart'; import 'package:plane/models/Workspace/workspace_model.dart'; import 'package:plane/provider/dashboard_provider.dart'; @@ -14,8 +14,8 @@ import 'package:plane/provider/projects_provider.dart'; import 'package:plane/provider/provider_list.dart'; import 'package:plane/provider/workspace_provider.dart'; import 'package:plane/repository/dashboard_service.dart'; -import 'package:plane/screens/MainScreens/Home/Dashboard/dash_board_screen.dart'; -import 'package:plane/screens/on_boarding/auth/setup_workspace.dart'; +import 'package:plane/screens/dashboard/dash_board_screen.dart'; +import 'package:plane/screens/onboarding/auth/setup_workspace.dart'; import 'package:plane/services/dio_service.dart'; import 'package:plane/utils/enums.dart'; import 'package:plane/widgets/custom_text.dart';