Skip to content

Commit 16a3469

Browse files
committed
Merge branch 'main' of github.com:devforth/adminforth-upload
2 parents d70da58 + 1ddca48 commit 16a3469

File tree

12 files changed

+895
-349
lines changed

12 files changed

+895
-349
lines changed

.woodpecker/buildSlackNotify.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ set -x
44

55
COMMIT_SHORT_SHA=$(echo $CI_COMMIT_SHA | cut -c1-8)
66

7+
STATUS=${1}
78

8-
if [ "$CI_STEP_STATUS" = "success" ]; then
9+
10+
if [ "$STATUS" = "success" ]; then
911
MESSAGE="Did a build without issues on \`$CI_REPO_NAME/$CI_COMMIT_BRANCH\`. Commit: _${CI_COMMIT_MESSAGE}_ (<$CI_COMMIT_URL|$COMMIT_SHORT_SHA>)"
1012

1113
curl -s -X POST -H "Content-Type: application/json" -d '{

.woodpecker/release.yml

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,42 @@ steps:
1616
commands:
1717
- infisical export --domain https://vault.devforth.io/api --format=dotenv-export --env="prod" > /woodpecker/deploy.vault.env
1818

19-
release:
19+
build:
2020
image: node:20
2121
when:
2222
- event: push
2323
commands:
2424
- apt update && apt install -y rsync
25-
- export $(cat /woodpecker/deploy.vault.env | xargs)
25+
- . /woodpecker/deploy.vault.env
2626
- npm clean-install
2727
- /bin/bash ./.woodpecker/buildRelease.sh
2828
- npm audit signatures
29+
30+
release:
31+
image: node:20
32+
when:
33+
- event:
34+
- push
35+
branch:
36+
- main
37+
commands:
38+
- . /woodpecker/deploy.vault.env
2939
- npx semantic-release
3040

3141
slack-on-failure:
42+
image: curlimages/curl
3243
when:
3344
- event: push
34-
status: [failure, success]
35-
- event: push
45+
status: [failure]
46+
commands:
47+
- . /woodpecker/deploy.vault.env
48+
- /bin/sh ./.woodpecker/buildSlackNotify.sh failure
49+
50+
slack-on-success:
3651
image: curlimages/curl
52+
when:
53+
- event: push
54+
status: [success]
3755
commands:
38-
- export $(cat /woodpecker/deploy.vault.env | xargs)
39-
- /bin/sh ./.woodpecker/buildSlackNotify.sh
40-
56+
- . /woodpecker/deploy.vault.env
57+
- /bin/sh ./.woodpecker/buildSlackNotify.sh success

custom/imageGenerator.vue

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
{{ $t('Generate image with AI') }}
1212
</h3>
1313
<button type="button"
14-
@click="emit('close')"
14+
@click="() => {stopGeneration = true; emit('close')}"
1515
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" >
1616
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
1717
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
@@ -161,7 +161,7 @@
161161
disabled:opacity-50 disabled:cursor-not-allowed"
162162
>{{ $t('Use image') }}</button>
163163
<button type="button" class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
164-
@click="emit('close')"
164+
@click="() => {stopGeneration = true; emit('close')}"
165165
>{{ $t('Cancel') }}</button>
166166
</div>
167167
</div>
@@ -181,6 +181,7 @@ import { callAdminForthApi } from '@/utils';
181181
import { useI18n } from 'vue-i18n';
182182
import adminforth from '@/adminforth';
183183
import { ProgressBar } from '@/afcl';
184+
import * as Handlebars from 'handlebars';
184185
185186
const { t: $t } = useI18n();
186187
@@ -190,6 +191,7 @@ const props = defineProps(['meta', 'record']);
190191
const images = ref([]);
191192
const loading = ref(false);
192193
const attachmentFiles = ref<string[]>([])
194+
const stopGeneration = ref(false);
193195
194196
function minifyField(field: string): string {
195197
if (field.length > 100) {
@@ -213,28 +215,9 @@ onMounted(async () => {
213215
}
214216
// iterate over all variables in template and replace them with their values from props.record[field].
215217
// if field is not present in props.record[field] then replace it with empty string and drop warning
216-
const regex = /{{(.*?)}}/g;
217-
const matches = template.match(regex);
218-
if (matches) {
219-
matches.forEach((match) => {
220-
const field = match.replace(/{{|}}/g, '').trim();
221-
if (field in context) {
222-
return;
223-
} else if (field in props.record) {
224-
context[field] = minifyField(props.record[field]);
225-
} else {
226-
adminforth.alert({
227-
message: $t('Field {{field}} defined in template but not found in record', { field }),
228-
variant: 'warning',
229-
timeout: 15,
230-
});
231-
}
232-
});
233-
}
234-
235-
prompt.value = template.replace(regex, (_, field) => {
236-
return context[field.trim()] || '';
237-
});
218+
const tpl = Handlebars.compile(template);
219+
const compiledTemplate = tpl(props.record);
220+
prompt.value = compiledTemplate;
238221
239222
const recordId = props.record[props.meta.recorPkFieldName];
240223
if (!recordId) return;
@@ -248,7 +231,6 @@ onMounted(async () => {
248231
249232
if (resp?.files?.length) {
250233
attachmentFiles.value = resp.files;
251-
console.log('attachmentFiles', attachmentFiles.value);
252234
}
253235
} catch (err) {
254236
console.error('Failed to fetch attachment files', err);
@@ -337,7 +319,7 @@ async function generateImages() {
337319
let error = null;
338320
try {
339321
resp = await callAdminForthApi({
340-
path: `/plugin/${props.meta.pluginInstanceId}/generate_images`,
322+
path: `/plugin/${props.meta.pluginInstanceId}/create-image-generation-job`,
341323
method: 'POST',
342324
body: {
343325
prompt: prompt.value,
@@ -346,16 +328,13 @@ async function generateImages() {
346328
});
347329
} catch (e) {
348330
console.error(e);
349-
} finally {
350-
clearInterval(ticker);
351-
loadingTimer.value = null;
352-
loading.value = false;
353331
}
332+
354333
if (resp?.error) {
355334
error = resp.error;
356335
}
357336
if (!resp) {
358-
error = $t('Error generating images, something went wrong');
337+
error = $t('Error creating image generation job');
359338
}
360339
361340
if (error) {
@@ -371,11 +350,55 @@ async function generateImages() {
371350
return;
372351
}
373352
353+
const jobId = resp.jobId;
354+
let jobStatus = null;
355+
let jobResponse = null;
356+
do {
357+
jobResponse = await callAdminForthApi({
358+
path: `/plugin/${props.meta.pluginInstanceId}/get-image-generation-job-status`,
359+
method: 'POST',
360+
body: { jobId },
361+
});
362+
if (jobResponse !== null) {
363+
if (jobResponse?.error) {
364+
error = jobResponse.error;
365+
break;
366+
};
367+
jobStatus = jobResponse?.job?.status;
368+
if (jobStatus === 'failed') {
369+
error = jobResponse?.job?.error || $t('Image generation job failed');
370+
}
371+
if (jobStatus === 'timeout') {
372+
error = jobResponse?.job?.error || $t('Image generation job timeout');
373+
}
374+
}
375+
await new Promise((resolve) => setTimeout(resolve, 2000));
376+
} while ((jobStatus === 'in_progress' || jobStatus === null) && !stopGeneration.value);
377+
378+
if (error) {
379+
adminforth.alert({
380+
message: error,
381+
variant: 'danger',
382+
timeout: 'unlimited',
383+
});
384+
clearInterval(ticker);
385+
loadingTimer.value = null;
386+
loading.value = false;
387+
return;
388+
}
389+
390+
const respImages = jobResponse?.job?.images || [];
391+
374392
images.value = [
375393
...images.value,
376-
...resp.images,
394+
...respImages,
377395
];
378396
397+
clearInterval(ticker);
398+
loadingTimer.value = null;
399+
loading.value = false;
400+
401+
379402
// images.value = [
380403
// 'https://via.placeholder.com/600x400?text=Image+1',
381404
// 'https://via.placeholder.com/600x400?text=Image+2',
@@ -386,7 +409,6 @@ async function generateImages() {
386409
caurosel.value = new Carousel(
387410
document.getElementById('gallery'),
388411
images.value.map((img, index) => {
389-
console.log('mapping image', img, index);
390412
return {
391413
image: img,
392414
el: document.getElementById('gallery').querySelector(`[data-carousel-item]:nth-child(${index + 1})`),

custom/package-lock.json

Lines changed: 65 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

custom/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"license": "ISC",
1212
"dependencies": {
1313
"@iconify-prerendered/vue-mdi": "^0.25.1718880438",
14+
"handlebars": "^4.7.8",
1415
"medium-zoom": "^1.1.0"
1516
}
1617
}

0 commit comments

Comments
 (0)