Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
weihan-plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Wei Han
weihan-plugin
Commits
3dd910fa
Commit
3dd910fa
authored
Oct 27, 2025
by
Wei Han
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
AddIssueDetails api progress
parent
1c3bdce0
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
190 additions
and
33 deletions
+190
-33
Info.plist
...PluginFramework/QmsPluginFramework.xcframework/Info.plist
+5
-5
QmsPluginFramework
...ios-arm64/QmsPluginFramework.framework/QmsPluginFramework
+0
-0
QmsPluginFramework
...simulator/QmsPluginFramework.framework/QmsPluginFramework
+0
-0
AddIssueAPIClient.h
...Framework/QmsPluginFramework/AddIssue/AddIssueAPIClient.h
+7
-1
AddIssueAPIClient.mm
...ramework/QmsPluginFramework/AddIssue/AddIssueAPIClient.mm
+91
-5
DetailsViewController.h
...ework/QmsPluginFramework/AddIssue/DetailsViewController.h
+7
-0
DetailsViewController.mm
...work/QmsPluginFramework/AddIssue/DetailsViewController.mm
+75
-17
PlanViewController.mm
...amework/QmsPluginFramework/AddIssue/PlanViewController.mm
+0
-0
Info.plist
ios/QmsPluginFramework.xcframework/Info.plist
+5
-5
QmsPluginFramework
...ios-arm64/QmsPluginFramework.framework/QmsPluginFramework
+0
-0
QmsPluginFramework
...simulator/QmsPluginFramework.framework/QmsPluginFramework
+0
-0
No files found.
framework/QmsPluginFramework/QmsPluginFramework.xcframework/Info.plist
View file @
3dd910fa
...
...
@@ -8,32 +8,32 @@
<
k
e
y
>
BinaryPath
<
/k
e
y
>
<
string
>
QmsPluginFramework.framework/QmsPluginFramework
<
/string
>
<
k
e
y
>
LibraryIdentifier
<
/k
e
y
>
<
string
>
ios-arm64
_x86_64-simulator
<
/string
>
<
string
>
ios-arm64
<
/string
>
<
k
e
y
>
LibraryPath
<
/k
e
y
>
<
string
>
QmsPluginFramework.framework
<
/string
>
<
k
e
y
>
SupportedArchitectures
<
/k
e
y
>
<
a
rr
a
y
>
<
string
>
arm64
<
/string
>
<
string
>
x86_64
<
/string
>
<
/
a
rr
a
y
>
<
k
e
y
>
SupportedPlatform
<
/k
e
y
>
<
string
>
ios
<
/string
>
<
k
e
y
>
SupportedPlatformVariant
<
/k
e
y
>
<
string
>
simulator
<
/string
>
<
/
d
i
c
t
>
<
d
i
c
t
>
<
k
e
y
>
BinaryPath
<
/k
e
y
>
<
string
>
QmsPluginFramework.framework/QmsPluginFramework
<
/string
>
<
k
e
y
>
LibraryIdentifier
<
/k
e
y
>
<
string
>
ios-arm64
<
/string
>
<
string
>
ios-arm64
_x86_64-simulator
<
/string
>
<
k
e
y
>
LibraryPath
<
/k
e
y
>
<
string
>
QmsPluginFramework.framework
<
/string
>
<
k
e
y
>
SupportedArchitectures
<
/k
e
y
>
<
a
rr
a
y
>
<
string
>
arm64
<
/string
>
<
string
>
x86_64
<
/string
>
<
/
a
rr
a
y
>
<
k
e
y
>
SupportedPlatform
<
/k
e
y
>
<
string
>
ios
<
/string
>
<
k
e
y
>
SupportedPlatformVariant
<
/k
e
y
>
<
string
>
simulator
<
/string
>
<
/
d
i
c
t
>
<
/
a
rr
a
y
>
<
k
e
y
>
CFBundlePackageType
<
/k
e
y
>
...
...
framework/QmsPluginFramework/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/QmsPluginFramework
View file @
3dd910fa
No preview for this file type
framework/QmsPluginFramework/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/QmsPluginFramework
View file @
3dd910fa
No preview for this file type
framework/QmsPluginFramework/QmsPluginFramework/AddIssue/AddIssueAPIClient.h
View file @
3dd910fa
// AddIssueAPIClient.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface
AddIssueAPIClient
:
NSObject
+
(
void
)
fetchGetUnitPlan
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
+
(
void
)
fetchSettingsByLocation
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
+
(
void
)
fetchSettingsByLocation
:(
NSString
*
)
locationID
projectID
:(
NSString
*
)
projectID
completion
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
+
(
void
)
submitAddIssue
:(
NSDictionary
*
)
params
images
:(
NSArray
<
UIImage
*>
*
)
images
completion
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
@end
framework/QmsPluginFramework/QmsPluginFramework/AddIssue/AddIssueAPIClient.mm
View file @
3dd910fa
...
...
@@ -90,8 +90,9 @@
[task resume];
}
+ (void)fetchSettingsByLocation:(void (^)(NSDictionary *data, NSError *error))completion{
// ✅ Build URL
+ (void)fetchSettingsByLocation:(NSString *)locationID
projectID:(NSString *)projectID
completion:(void (^)(NSDictionary *data, NSError *error))completion {
NSString *urlString = @"https://kitadev.commudesk.com/api/issue/getGeneralSettingByLocation?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImF0aGlyYWh6YWlkaUBjb252ZXAuY29tIiwicGFzc3dvcmQiOiIkMnkkMTAkNU9xYklqMnZ6UHJwckJrcVd5c3I2LmJCc1hVYS9Hd014eUhnL3RhUUhPUkNQcGdmTG8yakciLCJzdWIiOjIxNzAsImlzcyI6Imh0dHBzOi8va2l0YWRldi5jb21tdWRlc2suY29tL2FwaS9vd25lci9hdXRoL3Bhc3N3b3JkbGVzc19sb2dpbiIsImlhdCI6MTc2MDMxNTM1MiwiZXhwIjoyMDc1ODg0ODcyLCJuYmYiOjE3NjAzMTUzNTIsImp0aSI6IktoQmNyQnJEdDVNdDZlWmMifQ.JnxGbZ7hTeoOr6oibIzZMphgyKtTo2Aq9Efx6mrGfFA";
NSURL *url = [NSURL URLWithString:urlString];
...
...
@@ -118,8 +119,8 @@
// 🧩 Add POST fields
appendFormField(@"data[os]", @"AND");
appendFormField(@"data[project_id]",
@"8
");
appendFormField(@"data[location_id]",
@"1458"); //temp number
appendFormField(@"data[project_id]",
projectID ?: @"0
");
appendFormField(@"data[location_id]",
locationID ?: @"0");
NSString *deviceInfo = @"{\"OS\":\"AND\",\"IMEI\":\"AND:2a2f13ff17b1cbb5\",\"OS_VERSION\":\"35\",\"MODEL\":\"2306EPN60G\",\"APP_VERSION\":\"1.22.26\"}";
appendFormField(@"data[information]", deviceInfo);
...
...
@@ -177,6 +178,91 @@
[task resume];
}
+ (void)submitAddIssue:(NSDictionary *)issueData
images:(NSArray<UIImage *> * _Nullable)images
completion:(void (^)(NSDictionary * _Nullable response, NSError * _Nullable error))completion {
@end
NSString *urlString = @"https://kitadev.commudesk.com/api/owner/issue/addIssue?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImF0aGlyYWh6YWlkaUBjb252ZXAuY29tIiwicGFzc3dvcmQiOiIkMnkkMTAkNU9xYklqMnZ6UHJwckJrcVd5c3I2LmJCc1hVYS9Hd014eUhnL3RhUUhPUkNQcGdmTG8yakciLCJzdWIiOjIxNzAsImlzcyI6Imh0dHBzOi8va2l0YWRldi5jb21tdWRlc2suY29tL2FwaS9vd25lci9hdXRoL3Bhc3N3b3JkbGVzc19sb2dpbiIsImlhdCI6MTc2MDMxNTM1MiwiZXhwIjoyMDc1ODg0ODcyLCJuYmYiOjE3NjAzMTUzNTIsImp0aSI6IktoQmNyQnJEdDVNdDZlWmMifQ.JnxGbZ7hTeoOr6oibIzZMphgyKtTo2Aq9Efx6mrGfFA"; NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
// 🧱 Multipart body
NSString *boundary = [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]
forHTTPHeaderField:@"Content-Type"];
NSMutableData *body = [NSMutableData data];
// Helper for adding form fields
void (^appendFormField)(NSString *, NSString *) = ^(NSString *key, NSString *value) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", value]
dataUsingEncoding:NSUTF8StringEncoding]];
};
// 🔹 Append form data fields
for (NSString *key in issueData.allKeys) {
id value = issueData[key];
if ([value isKindOfClass:[NSNumber class]]) value = [(NSNumber *)value stringValue];
if ([value isKindOfClass:[NSString class]]) {
appendFormField([NSString stringWithFormat:@"data[%@]", key], value);
}
}
// 🔹 Append OS info
appendFormField(@"data[os]", @"AND");
// 🔹 Append images
if (images.count > 0) {
for (int i = 0; i < images.count; i++) {
UIImage *image = images[i];
NSData *imageData = UIImageJPEGRepresentation(image, 0.8);
if (!imageData) continue;
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:
@"Content-Disposition: form-data; name=\"data[image][%d]\"; filename=\"image%d.jpg\"\r\n", i, i]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:imageData];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
}
}
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary]
dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = body;
// Debug
NSLog(@"📦 [AddIssue] Uploading %lu image(s)", (unsigned long)images.count);
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"❌ [AddIssue] Network error: %@", error);
dispatch_async(dispatch_get_main_queue(), ^{ if (completion) completion(nil, error); });
return;
}
NSError *jsonErr;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonErr];
if (jsonErr) {
NSString *raw = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"⚠️ [AddIssue] JSON parse error: %@\nRaw response: %@", jsonErr, raw);
dispatch_async(dispatch_get_main_queue(), ^{ if (completion) completion(nil, jsonErr); });
return;
}
NSLog(@"✅ [AddIssue] Response: %@", json);
dispatch_async(dispatch_get_main_queue(), ^{ if (completion) completion(json, nil); });
}];
[task resume];
}
@end
framework/QmsPluginFramework/QmsPluginFramework/AddIssue/DetailsViewController.h
View file @
3dd910fa
...
...
@@ -15,4 +15,11 @@
@property
(
nonatomic
,
strong
)
NSString
*
projectCode
;
@property
(
nonatomic
,
strong
)
NSString
*
projectName
;
@property
(
nonatomic
,
assign
)
CGFloat
planX
;
@property
(
nonatomic
,
assign
)
CGFloat
planY
;
-
(
void
)
dismissSelf
;
-
(
void
)
handleSubmit
;
-
(
void
)
handleReset
;
@end
framework/QmsPluginFramework/QmsPluginFramework/AddIssue/DetailsViewController.mm
View file @
3dd910fa
#import "DetailsViewController.h"
#import "AddIssueAPIClient.h"
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@interface AddIssueDetailsViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property (nonatomic, strong) UIView *headerView;
...
...
@@ -10,12 +13,10 @@
@property (nonatomic, strong) NSArray *categories;
@property (nonatomic, strong) NSArray *types;
@property (nonatomic, strong) NSArray *issues;
@property (nonatomic, weak) UIButton *typeButton;
@property (nonatomic, weak) UIButton *issueButton;
@property (nonatomic, copy) NSString *selectedTypeName;
@property (nonatomic, copy) NSString * selectedIssueID;
@end
...
...
@@ -25,11 +26,15 @@
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
NSLog(@"📦 Data received in AddIssueDetailsViewController:\n planID: %@\n locationID: %@\n selectedLocationName: %@\n defectMatrix: %@
\n locationData: %@",
NSLog(@"📦 Data being brought over:\n planID: %@\n locationID: %@\n selectedLocationName: %@\n defectMatrix: %@\n projectName: %@\n projectCode: %@\n XCoordinates: %f\n YCoordinates: %f
\n locationData: %@",
self.planID,
self.locationID,
self.selectedLocationName,
self.defectMatrix,
self.projectName,
self.projectCode,
self.planX,
self.planY,
self.locationData);
NSDictionary *locData = self.locationData;
...
...
@@ -251,7 +256,7 @@
[locationField.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
]];
// === Reselect Button (
below the container, lef
t-aligned) ===
// === Reselect Button (
inside the container, righ
t-aligned) ===
UIButton *reselectBtn = [UIButton buttonWithType:UIButtonTypeSystem];
reselectBtn.translatesAutoresizingMaskIntoConstraints = NO;
[reselectBtn setTitle:@"Reselect" forState:UIControlStateNormal];
...
...
@@ -259,13 +264,15 @@
forState:UIControlStateNormal];
reselectBtn.titleLabel.font = [UIFont boldSystemFontOfSize:14];
[reselectBtn addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside];
[
content
addSubview:reselectBtn];
[
locationContainer
addSubview:reselectBtn];
[NSLayoutConstraint activateConstraints:@[
[reselectBtn.topAnchor constraintEqualToAnchor:locationContainer.bottomAnchor constant:4],
[reselectBtn.leadingAnchor constraintEqualToAnchor:locationContainer.leadingAnchor constant:4],
[reselectBtn.trailingAnchor constraintEqualToAnchor:locationContainer.trailingAnchor constant:-8],
[reselectBtn.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
// shrink locationField width so it doesn’t overlap
[locationField.trailingAnchor constraintEqualToAnchor:reselectBtn.leadingAnchor constant:-8],
]];
lastView = locationContainer;
// Category, Type, Issue — dropdown style
NSArray *titles = @[@"*Category", @"*Type", @"*Issue"];
...
...
@@ -302,12 +309,13 @@
NSArray *categories = self.locationData[@"category"];
if (categories.count > 0) {
NSDictionary *firstCategory = categories.firstObject;
NSString *categoryName =
firstCategory[@"cat_name"]
?: @"";
NSString *categoryName =
locationField.text
?: @"";
[dropdown setTitle:categoryName forState:UIControlStateNormal];
[dropdown setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
} else {
[dropdown setTitle:@"(No Category)" forState:UIControlStateNormal];
[dropdown setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
}
dropdown.enabled = NO; // make it non-clickable
...
...
@@ -444,6 +452,7 @@
return btn;
}
- (void)handleDropdownTap:(UIButton *)sender {
NSInteger tag = sender.tag;
NSString *title = sender.titleLabel.text ?: @"Select";
...
...
@@ -504,11 +513,32 @@
[sender setTitle:opt forState:UIControlStateNormal];
[sender setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
if (tag == 2001) { // Type
if (tag == 2001) {
// === Type dropdown ===
self.selectedTypeName = opt;
// Reset issue button when type changes
self.selectedIssueID = nil; // reset previous issue selection
[self.issueButton setTitle:@"- Select Issue -" forState:UIControlStateNormal];
[self.issueButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
NSLog(@"✅ Selected Type: %@", self.selectedTypeName);
} else if (tag == 2002) {
// === Issue dropdown ===
NSArray *issuesForType = @[];
for (NSDictionary *type in self.types) {
if ([type[@"type_name"] isEqualToString:self.selectedTypeName]) {
issuesForType = type[@"issue"];
break;
}
}
for (NSDictionary *issue in issuesForType) {
NSString *issueName = issue[@"issue_name"];
if ([issueName isEqualToString:opt]) {
self.selectedIssueID = [NSString stringWithFormat:@"%@", issue[@"issue_id"]];
NSLog(@"✅ Selected Issue: %@ (ID: %@)", issueName, self.selectedIssueID);
break;
}
}
}
}]];
}
...
...
@@ -711,11 +741,39 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
}
- (void)handleSubmit {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Submitted"
message:@"Issue has been added (mock)."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
NSLog(@"Calling addIssue API:\n planID: %@\n locationID: %@\n selectedIssueID: %@\n XCoordinates: %f\n YCoordinates: %f\n commentField: %@",
self.planID,
self.locationID,
self.selectedIssueID,
self.planX,
self.planY,
self.commentField);
NSDictionary *issueData = @{
@"plan_id": self.planID ?: @"0",
@"location_id": self.locationID ?: @"0",
@"issue_setting_id": self.selectedIssueID ?: @"",
@"position_x": [NSString stringWithFormat:@"%f", self.planX ?: 0.0],
@"position_y": [NSString stringWithFormat:@"%f", self.planY ?: 0.0],
@"comment": self.commentField ?: @"",
@"os": @"AND"
};
[AddIssueAPIClient submitAddIssue:issueData
images:self.uploadedImages
completion:^(NSDictionary *response, NSError *error) {
if (error) {
NSLog(@"❌ Submission failed: %@", error.localizedDescription);
return;
}
NSDictionary *appData = response[@"AppData"];
if ([appData[@"status"] isEqualToString:@"success"]) {
NSLog(@"✅ Issue submitted successfully!");
} else {
NSLog(@"⚠️ API Error: %@", appData[@"message"]);
}
}];
}
@end
framework/QmsPluginFramework/QmsPluginFramework/AddIssue/PlanViewController.mm
View file @
3dd910fa
This diff is collapsed.
Click to expand it.
ios/QmsPluginFramework.xcframework/Info.plist
View file @
3dd910fa
...
...
@@ -8,32 +8,32 @@
<
k
e
y
>
BinaryPath
<
/k
e
y
>
<
string
>
QmsPluginFramework.framework/QmsPluginFramework
<
/string
>
<
k
e
y
>
LibraryIdentifier
<
/k
e
y
>
<
string
>
ios-arm64
_x86_64-simulator
<
/string
>
<
string
>
ios-arm64
<
/string
>
<
k
e
y
>
LibraryPath
<
/k
e
y
>
<
string
>
QmsPluginFramework.framework
<
/string
>
<
k
e
y
>
SupportedArchitectures
<
/k
e
y
>
<
a
rr
a
y
>
<
string
>
arm64
<
/string
>
<
string
>
x86_64
<
/string
>
<
/
a
rr
a
y
>
<
k
e
y
>
SupportedPlatform
<
/k
e
y
>
<
string
>
ios
<
/string
>
<
k
e
y
>
SupportedPlatformVariant
<
/k
e
y
>
<
string
>
simulator
<
/string
>
<
/
d
i
c
t
>
<
d
i
c
t
>
<
k
e
y
>
BinaryPath
<
/k
e
y
>
<
string
>
QmsPluginFramework.framework/QmsPluginFramework
<
/string
>
<
k
e
y
>
LibraryIdentifier
<
/k
e
y
>
<
string
>
ios-arm64
<
/string
>
<
string
>
ios-arm64
_x86_64-simulator
<
/string
>
<
k
e
y
>
LibraryPath
<
/k
e
y
>
<
string
>
QmsPluginFramework.framework
<
/string
>
<
k
e
y
>
SupportedArchitectures
<
/k
e
y
>
<
a
rr
a
y
>
<
string
>
arm64
<
/string
>
<
string
>
x86_64
<
/string
>
<
/
a
rr
a
y
>
<
k
e
y
>
SupportedPlatform
<
/k
e
y
>
<
string
>
ios
<
/string
>
<
k
e
y
>
SupportedPlatformVariant
<
/k
e
y
>
<
string
>
simulator
<
/string
>
<
/
d
i
c
t
>
<
/
a
rr
a
y
>
<
k
e
y
>
CFBundlePackageType
<
/k
e
y
>
...
...
ios/QmsPluginFramework.xcframework/ios-arm64/QmsPluginFramework.framework/QmsPluginFramework
View file @
3dd910fa
No preview for this file type
ios/QmsPluginFramework.xcframework/ios-arm64_x86_64-simulator/QmsPluginFramework.framework/QmsPluginFramework
View file @
3dd910fa
No preview for this file type
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment