Skip to content

Commit 6937fb0

Browse files
authored
Merge pull request #3676 from bakaphp/development
Version 1.36.0
2 parents 9344d61 + bb3a20c commit 6937fb0

File tree

12 files changed

+519
-6
lines changed

12 files changed

+519
-6
lines changed

app/Console/Commands/Workflows/KanvasWorkflowSynActionCommand.php

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Kanvas\Connectors\NetSuite\Workflow\SyncPeopleWithNetSuiteActivity;
3434
use Kanvas\Connectors\OfferLogix\Workflow\SoftPullActivity;
3535
use Kanvas\Connectors\OfferLogix\Workflow\SoftPullFromLeadActivity;
36+
use Kanvas\Connectors\PromptMine\Workflows\Activities\PromptImageFilterActivity;
3637
use Kanvas\Connectors\PromptMine\Workflows\Activities\SaveLlmChoiceActivity;
3738
use Kanvas\Connectors\RainForest\Workflows\Activities\ImportProductActivity;
3839
use Kanvas\Connectors\Recombee\Workflows\PushMessageToItemActivity;
@@ -149,6 +150,7 @@ public function handle(): void
149150
StripePaymentIntentWebhookJob::class,
150151
UpdateOrderStripePaymentActivity::class,
151152
AttachFileToChecklistItemActivity::class,
153+
PromptImageFilterActivity::class,
152154
];
153155

154156
$createdActions = [];

app/GraphQL/Inventory/Mutations/Products/Products.php

+16
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Kanvas\Inventory\Products\DataTransferObject\Product as ProductDto;
1414
use Kanvas\Inventory\Products\DataTransferObject\Translate as ProductTranslateDto;
1515
use Kanvas\Inventory\Products\Models\Products as ProductsModel;
16+
use Kanvas\Inventory\Products\Models\ProductsAttributes;
1617
use Kanvas\Inventory\Products\Repositories\ProductsRepository;
1718
use Kanvas\Inventory\Status\Repositories\StatusRepository;
1819
use Kanvas\Inventory\Variants\Models\Variants;
@@ -165,4 +166,19 @@ public function updateProductTranslation(mixed $root, array $req): ProductsModel
165166

166167
return $product;
167168
}
169+
170+
public function updateProductAttributeTranslation(mixed $root, array $req): ProductsAttributes
171+
{
172+
$company = auth()->user()->getCurrentCompany();
173+
$language = Languages::getByCode($req['code']);
174+
$attribute = AttributesRepository::getById((int) $req['attribute_id'], $company);
175+
$product = ProductsRepository::getById((int) $req['product_id'], $company);
176+
177+
$productAttribute = $product->attributeValues('attribute_id', $attribute->getId())->firstOrFail();
178+
$value = $req['value'];
179+
$productAttribute->setTranslation('value', $language->code, $value);
180+
$productAttribute->save();
181+
182+
return $productAttribute;
183+
}
168184
}

app/GraphQL/Inventory/Mutations/Variants/Variants.php

+16
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Kanvas\Inventory\Variants\DataTransferObject\Variants as VariantDto;
2020
use Kanvas\Inventory\Variants\DataTransferObject\VariantsWarehouses;
2121
use Kanvas\Inventory\Variants\Models\Variants as VariantModel;
22+
use Kanvas\Inventory\Variants\Models\VariantsAttributes;
2223
use Kanvas\Inventory\Variants\Models\VariantsChannels;
2324
use Kanvas\Inventory\Variants\Models\VariantsWarehouses as ModelsVariantsWarehouses;
2425
use Kanvas\Inventory\Variants\Repositories\VariantsRepository;
@@ -296,4 +297,19 @@ public function updateVariantTranslation(mixed $root, array $req): VariantModel
296297

297298
return $variant;
298299
}
300+
301+
public function updateVariantAttributeTranslation(mixed $root, array $req): VariantsAttributes
302+
{
303+
$company = auth()->user()->getCurrentCompany();
304+
$language = Languages::getByCode($req['code']);
305+
$attribute = AttributesRepository::getById((int) $req['attribute_id'], $company);
306+
$variant = VariantsRepository::getById((int) $req['variant_id'], $company);
307+
308+
$variantAttribute = $variant->attributeValues('attribute_id', $attribute->getId())->firstOrFail();
309+
$value = $req['value'];
310+
$variantAttribute->setTranslation('value', $language->code, $value);
311+
$variantAttribute->save();
312+
313+
return $variantAttribute;
314+
}
299315
}

graphql/schemas/Inventory/attributes.graphql

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ type AttributeTranslation {
7272
}
7373

7474
type AttributeValueTranslation {
75-
value: String
75+
value: Mixed
7676
language: LanguageDisplay!
7777
}
7878

graphql/schemas/Inventory/product.graphql

+19
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ type ProductTranslation {
6565
language: LanguageDisplay!
6666
}
6767

68+
type ProductAttributesValue {
69+
product: Product!
70+
attribute: Attributes!
71+
translation(languageCode: String!): AttributeValueTranslation
72+
@field(
73+
resolver: "App\\GraphQL\\Translation\\Resolvers\\TranslationResolver@translation"
74+
)
75+
value: Mixed
76+
}
77+
6878
input ProductInput {
6979
products_types_id: ID
7080
sku: String @rules(apply: ["required_without:variants"])
@@ -177,6 +187,15 @@ extend type Mutation @guard {
177187
@field(
178188
resolver: "App\\GraphQL\\Inventory\\Mutations\\Products\\Products@addCategory"
179189
)
190+
updateProductAttributeTranslations(
191+
product_id: ID!
192+
attribute_id: ID!
193+
code: String!
194+
value: Mixed
195+
): ProductAttributesValue!
196+
@field(
197+
resolver: "App\\GraphQL\\Inventory\\Mutations\\Products\\Products@updateProductAttributeTranslation"
198+
)
180199
}
181200

182201
extend type Query @guard {

graphql/schemas/Inventory/variant.graphql

+19
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ type VariantPricingInfo {
6262
config: Mixed
6363
}
6464

65+
type VariantAttributesValue {
66+
variant: Variant!
67+
attribute: Attributes!
68+
translation(languageCode: String!): AttributeValueTranslation
69+
@field(
70+
resolver: "App\\GraphQL\\Translation\\Resolvers\\TranslationResolver@translation"
71+
)
72+
value: Mixed
73+
}
74+
6575
#@deprecated(reason: "Use the ProductAttributesInput type instead")
6676
input VariantsAttributesInput {
6777
id: ID
@@ -137,6 +147,15 @@ extend type Mutation @guard {
137147
@field(
138148
resolver: "App\\GraphQL\\Inventory\\Mutations\\Variants\\Variants@updateVariantTranslation"
139149
)
150+
updateVariantAttributeTranslations(
151+
variant_id: ID!
152+
attribute_id: ID!
153+
code: String!
154+
value: Mixed
155+
): VariantAttributesValue!
156+
@field(
157+
resolver: "App\\GraphQL\\Inventory\\Mutations\\Variants\\Variants@updateVariantAttributeTranslation"
158+
)
140159
uploadFileToVariant(id: ID!, file: Upload!): Product!
141160
@field(
142161
resolver: "App\\GraphQL\\Inventory\\Mutations\\Variants\\VariantMediaMutation@attachFileToVariant"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Kanvas\Connectors\PromptMine\Workflows\Activities;
6+
7+
use Baka\Contracts\AppInterface;
8+
use Exception;
9+
use Illuminate\Database\Eloquent\Model;
10+
use Illuminate\Support\Facades\Http;
11+
use Kanvas\Workflow\Contracts\WorkflowActivityInterface;
12+
use Kanvas\Workflow\KanvasActivity;
13+
use Override;
14+
15+
class PromptImageFilterActivity extends KanvasActivity implements WorkflowActivityInterface
16+
{
17+
protected ?string $apiUrl = null;
18+
protected const int MAX_STATUS_CHECKS = 30;
19+
protected const int STATUS_CHECK_DELAY = 2;
20+
public $tries = 3;
21+
22+
#[Override]
23+
public function execute(Model $entity, AppInterface $app, array $params): array
24+
{
25+
$messageFiles = $entity->getFiles();
26+
$this->apiUrl = $entity->app->get('PROMPT_IMAGE_API_URL');
27+
28+
if (empty($this->apiUrl)) {
29+
return [
30+
'result' => false,
31+
'message' => 'API URL not configured',
32+
];
33+
}
34+
35+
if ($messageFiles->isEmpty()) {
36+
return [
37+
'result' => false,
38+
'message' => 'Message does not have any files',
39+
];
40+
}
41+
42+
$fileUrl = $messageFiles->first()->url;
43+
44+
try {
45+
// Step 1: Submit the image for processing
46+
$submitResponse = $this->submitImage($fileUrl);
47+
48+
if (! isset($submitResponse['request_id'])) {
49+
return [
50+
'result' => false,
51+
'message' => 'Failed to submit image for processing',
52+
];
53+
}
54+
55+
$requestId = $submitResponse['request_id'];
56+
57+
// Step 2: Check processing status until complete
58+
$statusResponse = $this->checkProcessingStatus($requestId);
59+
60+
if ($statusResponse['status'] !== 'COMPLETED') {
61+
return [
62+
'result' => false,
63+
'message' => 'Image processing did not complete successfully',
64+
];
65+
}
66+
67+
// Step 3: Get the processed image result
68+
$resultResponse = $this->getProcessingResult($requestId);
69+
70+
if (! isset($resultResponse['data']['image']['url'])) {
71+
return [
72+
'result' => false,
73+
'message' => 'Failed to retrieve processed image',
74+
];
75+
}
76+
77+
$processedImageUrl = $resultResponse['data']['image']['url'];
78+
79+
return [
80+
'message' => 'Image processed successfully',
81+
'result' => true,
82+
'user_id' => $entity->user->getId(),
83+
'message_data' => $entity->message,
84+
'message_id' => $entity->getId(),
85+
'processed_image_url' => $processedImageUrl,
86+
'original_image_url' => $fileUrl,
87+
'request_id' => $requestId,
88+
];
89+
} catch (Exception $e) {
90+
return [
91+
'result' => false,
92+
'message_id' => $entity->getId(),
93+
'message' => 'Error processing image: ' . $e->getMessage(),
94+
];
95+
}
96+
}
97+
98+
/**
99+
* Submit an image for processing
100+
*/
101+
protected function submitImage(string $imageUrl): array
102+
{
103+
$response = Http::withHeaders([
104+
'Content-Type' => 'application/json',
105+
])->post($this->apiUrl, [
106+
'operation' => 'submit',
107+
'image_url' => $imageUrl,
108+
'model' => 'fal-ai/ghiblify',
109+
]);
110+
111+
return $response->json();
112+
}
113+
114+
/**
115+
* Check the processing status of a submitted image
116+
*/
117+
protected function checkProcessingStatus(string $requestId): array
118+
{
119+
$attempts = 0;
120+
$statusResponse = [];
121+
122+
while ($attempts < self::MAX_STATUS_CHECKS) {
123+
$response = Http::withHeaders([
124+
'Content-Type' => 'application/json',
125+
])->post($this->apiUrl, [
126+
'operation' => 'status',
127+
'requestId' => $requestId,
128+
'model' => 'fal-ai/ghiblify',
129+
'logs' => true,
130+
]);
131+
132+
$statusResponse = $response->json();
133+
134+
if ($statusResponse['status'] === 'COMPLETED') {
135+
break;
136+
}
137+
138+
if ($statusResponse['status'] === 'FAILED') {
139+
throw new Exception('Image processing failed for this request' . $requestId);
140+
}
141+
142+
// Wait before checking again
143+
sleep(self::STATUS_CHECK_DELAY);
144+
$attempts++;
145+
}
146+
147+
if ($attempts >= self::MAX_STATUS_CHECKS) {
148+
throw new Exception('Image processing timed out' . $requestId);
149+
}
150+
151+
return $statusResponse;
152+
}
153+
154+
/**
155+
* Get the result of a processed image
156+
*/
157+
protected function getProcessingResult(string $requestId): array
158+
{
159+
$response = Http::withHeaders([
160+
'Content-Type' => 'application/json',
161+
])->post($this->apiUrl, [
162+
'operation' => 'result',
163+
'requestId' => $requestId,
164+
'model' => 'fal-ai/ghiblify',
165+
]);
166+
167+
return $response->json();
168+
}
169+
}

src/Domains/Connectors/Shopify/Enums/ConfigEnum.php

+1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ enum ConfigEnum: string
1010
case VARIANT_LIMIT = 'variant-limit';
1111
case SHOPIFY_VENDOR_DEFAULT_NAME = 'shopify-vendor-default-name';
1212
case SHOPIFY_PRODUCT_TYPE_AS_CATEGORY = 'shopify-product-type-as-category';
13+
case SHOPIFY_PUBLICATION_ID = 'shopify-publication-id';
1314
}

0 commit comments

Comments
 (0)