Skip to content

Commit

Permalink
feat(block-editor): AI Image prompt Block (#26405) (#26485)
Browse files Browse the repository at this point in the history
* Created AI content node

* Created ai-content-service

* Created AI prompt content extension

* Update ai-content.service.ts

* Optimised and aligned extension code

* Resolved comments on PR

* Removed ai content node file

* Update ai-content.service.ts

* Remove import path for ai-content-node

* Updated the ai-prompt form

* align ai text prompt extension

* Resovled comments on pull

* Fix the aiTextPrompt form

* Updated extension related code

* Update ai-content-prompt.plugin.ts

* Remove some extra code

* Fixed outside click for aiContentPrompt extension

* Created ai content node

* Updated ai-content node

* Remove unused code, resolve comments on PR

* ai-content-prompt extension code optimisation

* Update ai-content-prompt.plugin.ts

* Integrated with AI api

* insert ai node on response

* textPrompt extension code optimsation

* Update ai-content.service.ts

* Resolve comments on pull req

* handle close extension on outside click and content flip fix

* Added focus field method and type for form

* Change name of ai node creation command

* Update the ai-content icon in the actions menu list

* Update ai-content-prompt.component.scss

* Resolved comments on pull

* Added pening status and update the name of destroy var

* Implement ai-content-actions extension

* ai-prompt extension code optimisation

* ai-text-prompt block optimisation

* Update main.ts

* feat: Created ai image prompt extension

* Resolve comments on pull

* Created loader node and handle loading image

* Resolve comments on PR

* Code optimisation for ai-content-actions extension

* Fix css for p-listbox

* Handle ai content actions to work in two diff context, code optimisation

* Code optimisation

* clean code from extra code

---------

Co-authored-by: Nikola Trajkovic <82508651+nikolatrajkovic24@users.noreply.github.com>
Co-authored-by: Nikola <nikola@physician.me>
Co-authored-by: Will Ezell <will@dotcms.com>
  • Loading branch information
4 people authored Oct 20, 2023
1 parent 4a007bc commit 5bd7635
Show file tree
Hide file tree
Showing 22 changed files with 819 additions and 34 deletions.
7 changes: 5 additions & 2 deletions core-web/libs/block-editor/src/lib/block-editor.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { DotEditorCountBarComponent } from './components/dot-editor-count-bar/do
import {
AIContentPromptComponent,
AIContentActionsComponent,
AIImagePromptComponent,
BubbleLinkFormComponent,
BubbleMenuButtonComponent,
BubbleMenuComponent,
Expand Down Expand Up @@ -54,7 +55,8 @@ import { SharedModule } from './shared/shared.module';
DotEditorCountBarComponent,
FloatingButtonComponent,
AIContentPromptComponent,
AIContentActionsComponent
AIContentActionsComponent,
AIImagePromptComponent
],
providers: [DotUploadFileService, LoggerService, StringUtils, AiContentService],
exports: [
Expand All @@ -66,7 +68,8 @@ import { SharedModule } from './shared/shared.module';
BubbleFormComponent,
DotBlockEditorComponent,
AIContentPromptComponent,
AIContentActionsComponent
AIContentActionsComponent,
AIImagePromptComponent
]
})
export class BlockEditorModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,38 @@
border: 1px solid $color-palette-primary-300;
}
}

.loader-style {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
min-height: 12.5rem;
min-width: 25rem;
width: 25.5625rem;
height: 17.375rem;
padding: 0.5rem;
border-radius: 0.5rem;
border: 1.5px solid $color-palette-gray-400;
}

.p-progress-spinner {
border: 5px solid $color-palette-gray-300;
border-radius: 50%;
border-top: 5px solid $color-palette-primary;
width: 2.4rem;
height: 2.4rem;
animation: spin 1s linear infinite;
}

@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
}

tiptap-editor {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,19 @@ import {
AssetUploader,
DotComands,
AIContentPromptExtension,
AIImagePromptExtension,
AIContentActionsExtension
} from '../../extensions';
import { DotPlaceholder } from '../../extensions/dot-placeholder/dot-placeholder-plugin';
import { ContentletBlock, ImageNode, VideoNode, AIContentNode } from '../../nodes';
import { ContentletBlock, ImageNode, VideoNode, AIContentNode, LoaderNode } from '../../nodes';
import {
formatHTML,
removeInvalidNodes,
SetDocAttrStep,
DotMarketingConfigService,
RestoreDefaultDOMAttrs
} from '../../shared';

@Component({
selector: 'dot-block-editor',
templateUrl: './dot-block-editor.component.html',
Expand Down Expand Up @@ -111,7 +113,8 @@ export class DotBlockEditorComponent implements OnInit, OnDestroy {
['image', ImageNode],
['video', VideoNode],
['table', DotTableExtension()],
['aiContent', AIContentNode]
['aiContent', AIContentNode],
['loader', LoaderNode]
]);

private destroy$: Subject<boolean> = new Subject<boolean>();
Expand Down Expand Up @@ -383,6 +386,7 @@ export class DotBlockEditorComponent implements OnInit, OnDestroy {
DotBubbleMenuExtension(this.viewContainerRef),
BubbleFormExtension(this.viewContainerRef),
AIContentPromptExtension(this.viewContainerRef),
AIImagePromptExtension(this.viewContainerRef),
AIContentActionsExtension(this.viewContainerRef),
DotFloatingButton(this.injector, this.viewContainerRef),
DotTableCellExtension(this.viewContainerRef),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ function execCommand({
superscript: () => editor.chain().setSuperscript().focus().run(),
video: () => editor.commands.openAssetForm({ type: 'video' }),
aiContentPrompt: () => editor.commands.openAIPrompt(),
aiContent: () => editor.commands.insertAINode()
aiContent: () => editor.commands.insertAINode(),
aiImagePrompt: () => editor.commands.openImagePrompt()
};

getCustomActions(customBlocks).forEach((option) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Observable, of } from 'rxjs';
import { Observable } from 'rxjs';

import { Component, EventEmitter, Output, OnInit } from '@angular/core';

Expand Down Expand Up @@ -26,6 +26,7 @@ export class AIContentActionsComponent implements OnInit {
@Output() actionEmitter = new EventEmitter<ACTIONS>();

actionOptions!: ActionOption[];
tooltipContent = 'Describe the size, color palette, style, mood, etc.';

constructor(private aiContentService: AiContentService) {}

Expand Down Expand Up @@ -56,17 +57,11 @@ export class AIContentActionsComponent implements OnInit {
this.actionEmitter.emit(action);
}

getLatestContent() {
return this.aiContentService.getLastContentResponse();
getLatestContent(): string {
return this.aiContentService.getLatestContent();
}

getNewContent(): Observable<string> {
const promptToUse: string = this.aiContentService.getLastUsedPrompt();

if (promptToUse) {
return this.aiContentService.getIAContent(promptToUse);
}

return of('');
getNewContent(contentType: string): Observable<string> {
return this.aiContentService.getNewContent(contentType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import tippy, { Instance, Props } from 'tippy.js';

import { ComponentRef } from '@angular/core';

import { take, takeUntil } from 'rxjs/operators';
import { takeUntil } from 'rxjs/operators';

import { Editor } from '@tiptap/core';

Expand Down Expand Up @@ -88,18 +88,27 @@ export class AIContentActionsView {
}

private generateContent() {
const nodeType = this.getNodeType();

this.editor.commands.closeAIContentActions();

this.component.instance
.getNewContent()
.pipe(take(1), takeUntil(this.destroy$))
.subscribe((newContent) => {
if (newContent) {
this.editor.commands.deleteSelection();
this.editor.commands.insertAINode(newContent);
this.editor.commands.openAIContentActions();
}
});
this.component.instance.getNewContent(nodeType).subscribe((newContent) => {
if (newContent) {
this.editor.commands.deleteSelection();
this.editor.commands.insertAINode(newContent);
this.editor.commands.openAIContentActions();
}
});
}

private getNodeType() {
const { state } = this.editor.view;
const { doc, selection } = state;
const { ranges } = selection;
const from = Math.min(...ranges.map((range) => range.$from.pos));
const node = doc?.nodeAt(from);

return node.type.name;
}

private deleteContent() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<div class="ai-image-dialog">
<p class="title">Generate AI Image</p>
<div class="choice-div-container">
<div class="choice-div" (click)="openFormOne()">
<div class="icon-wrapper">
<svg
width="40"
height="40"
viewBox="0 0 40 40"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M5.02857 11C3.69491 11 2.41587 11.5234 1.47283 12.455C0.529794 13.3866 0 14.6502 0 15.9677V34.0323C0 35.3498 0.529794 36.6133 1.47283 37.545C2.41587 38.4766 3.69491 39 5.02857 39H26.9714C28.3051 39 29.5841 38.4766 30.5272 37.545C31.4702 36.6133 32 35.3498 32 34.0323V34L32 33.4L29.2571 30.7626L24.2834 25.849C24.1534 25.7117 23.994 25.6048 23.8169 25.5361C23.6397 25.4673 23.4493 25.4385 23.2594 25.4516C23.0674 25.4627 22.8795 25.5115 22.7068 25.5952C22.5341 25.679 22.38 25.796 22.2537 25.9394L19.8949 28.7394L11.4834 20.4297C11.3595 20.2996 11.209 20.1969 11.042 20.1284C10.8749 20.0598 10.6951 20.0271 10.5143 20.0323C10.3222 20.0433 10.1343 20.0921 9.96162 20.1759C9.78891 20.2596 9.63488 20.3766 9.50857 20.52L2.74286 28.4865V15.9677C2.74286 15.3689 2.98367 14.7945 3.41233 14.371C3.84098 13.9476 4.42236 13.7097 5.02857 13.7097H14.2194V12.3548V11H5.02857ZM2.74316 34.0326V32.7139L10.606 23.3926L18.1397 30.8352L13.5317 36.2545H5.02888C4.42895 36.2546 3.85305 36.0217 3.42543 35.606C2.99781 35.1903 2.75276 34.6252 2.74316 34.0326ZM17.0975 36.2906L23.406 28.8119L29.166 34.5023C29.0649 35.0045 28.7913 35.4568 28.3914 35.7827C27.9916 36.1086 27.4901 36.288 26.9717 36.2906H22.0346H17.0975Z"
fill="#8D92A5" />
<path
d="M28.6935 19.2671L22.8007 21.0668C22.6478 21.1134 22.5136 21.2101 22.4181 21.3425C22.3227 21.4749 22.2711 21.6357 22.2711 21.8011C22.2711 21.9664 22.3227 22.1273 22.4181 22.2597C22.5136 22.392 22.6478 22.4887 22.8007 22.5353L28.6935 24.3351L30.4277 30.4505C30.4726 30.6091 30.5658 30.7484 30.6933 30.8474C30.8209 30.9465 30.9759 31 31.1352 31C31.2945 31 31.4495 30.9465 31.577 30.8474C31.7045 30.7484 31.7977 30.6091 31.8427 30.4505L33.5776 24.3351L39.4704 22.5353C39.6233 22.4887 39.7575 22.392 39.8529 22.2597C39.9484 22.1273 40 21.9664 40 21.8011C40 21.6357 39.9484 21.4749 39.8529 21.3425C39.7575 21.2101 39.6233 21.1134 39.4704 21.0668L33.5776 19.2671L31.8427 13.1517C31.7978 12.993 31.7046 12.8538 31.577 12.7547C31.4495 12.6556 31.2945 12.6021 31.1352 12.6021C30.9759 12.6021 30.8208 12.6556 30.6933 12.7547C30.5658 12.8538 30.4726 12.993 30.4277 13.1517L28.6935 19.2671Z"
fill="#7042F0" />
<path
d="M35.9026 8.29011L39.0994 7.31284C39.2522 7.26623 39.3864 7.16951 39.4819 7.03716C39.5773 6.9048 39.6289 6.74394 39.6289 6.57862C39.6289 6.41331 39.5773 6.25244 39.4819 6.12008C39.3864 5.98773 39.2522 5.89101 39.0994 5.8444L35.9026 4.8679L34.9609 1.54959C34.916 1.39096 34.8228 1.25169 34.6953 1.15262C34.5677 1.05354 34.4127 1 34.2534 1C34.0941 1 33.9391 1.05354 33.8115 1.15262C33.684 1.25169 33.5908 1.39096 33.5459 1.54959L32.6049 4.8679L29.4075 5.8444C29.2546 5.891 29.1204 5.98771 29.025 6.12006C28.9295 6.25241 28.8779 6.41329 28.8779 6.57862C28.8779 6.74395 28.9295 6.90483 29.025 7.03718C29.1204 7.16953 29.2546 7.26624 29.4075 7.31284L32.6049 8.29011L33.5459 11.6076C33.5908 11.7663 33.684 11.9056 33.8115 12.0046C33.9391 12.1037 34.0941 12.1572 34.2534 12.1572C34.4127 12.1572 34.5677 12.1037 34.6953 12.0046C34.8228 11.9056 34.916 11.7663 34.9609 11.6076L35.9026 8.29011Z"
fill="#7042F0" />
<path
d="M19.6845 9.67937L16.459 11.0447C16.3233 11.1021 16.2072 11.2002 16.1254 11.3265C16.0437 11.4527 16 11.6014 16 11.7535C16 11.9056 16.0437 12.0542 16.1254 12.1805C16.2072 12.3067 16.3233 12.4048 16.459 12.4623L19.6845 13.8276L21.0001 17.175C21.0555 17.3159 21.1501 17.4364 21.2717 17.5212C21.3934 17.606 21.5366 17.6514 21.6832 17.6514C21.8297 17.6514 21.973 17.606 22.0946 17.5212C22.2163 17.4364 22.3108 17.3159 22.3662 17.175L23.6818 13.8276L26.9067 12.4623C27.0424 12.4048 27.1585 12.3067 27.2402 12.1805C27.322 12.0542 27.3656 11.9056 27.3656 11.7535C27.3656 11.6014 27.322 11.4527 27.2402 11.3265C27.1585 11.2002 27.0424 11.1021 26.9067 11.0447L23.6818 9.67937L22.3662 6.33266C22.3108 6.19183 22.2163 6.07132 22.0946 5.98648C21.973 5.90165 21.8297 5.85635 21.6832 5.85635C21.5366 5.85635 21.3934 5.90165 21.2717 5.98648C21.1501 6.07132 21.0555 6.19183 21.0001 6.33266L19.6845 9.67937Z"
fill="#7042F0" />
</svg>
</div>
<span>
<span
><strong>Generate</strong> an AI image based on your input and requests.
</span>

<p-button
[style]="{
'background-color': 'white',
color: '#426BF0',
height: 'unset',
width: 'unset',
padding: '0',
margin: '0',
outline: 'none'
}"
pTooltip="Describe the type of image you want to generate."
tooltipPosition="top"
icon="pi pi-info-circle"
tooltipZIndex="999999">
</p-button>
</span>

<form *ngIf="showFormOne" [formGroup]="form" (ngSubmit)="onSubmit()" autocomplete="off">
<div class="input-field-wrapper">
<textarea
class="input-field"
placeholder="Create a realistic image of a cow in the snow."
formControlName="promptGenerate"></textarea>
</div>

<div class="submit-btn-container">
<p-button icon="pi pi-send" type="submit" label="Generate"> </p-button>
</div>
</form>
</div>

<div class="choice-div" (click)="openFormTwo()">
<div class="icon-wrapper">
<svg
width="34"
height="42"
viewBox="0 0 34 42"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M17.9594 25.5195L9.80768 28.0091C9.59623 28.0736 9.41058 28.2074 9.27852 28.3905C9.14646 28.5736 9.07509 28.7961 9.07509 29.0248C9.07509 29.2535 9.14646 29.4761 9.27852 29.6592C9.41058 29.8423 9.59623 29.9761 9.80768 30.0405L17.9594 32.5302L20.3584 40.9899C20.4205 41.2093 20.5494 41.4019 20.7259 41.5389C20.9023 41.6759 21.1167 41.75 21.3371 41.75C21.5574 41.75 21.7719 41.6759 21.9483 41.5389C22.1247 41.4019 22.2536 41.2093 22.3158 40.9899L24.7158 32.5302L32.8675 30.0405C33.079 29.9761 33.2646 29.8423 33.3967 29.6592C33.5287 29.4761 33.6001 29.2535 33.6001 29.0248C33.6001 28.7961 33.5287 28.5736 33.3967 28.3905C33.2646 28.2074 33.079 28.0736 32.8675 28.0091L24.7158 25.5195L22.3158 17.0598C22.2537 16.8404 22.1248 16.6477 21.9483 16.5107C21.7719 16.3736 21.5575 16.2995 21.3371 16.2995C21.1167 16.2995 20.9023 16.3736 20.7258 16.5107C20.5494 16.6477 20.4205 16.8404 20.3584 17.0598L17.9594 25.5195Z"
fill="#7042F0" />
<path
d="M27.9321 10.3346L32.3543 8.98276C32.5657 8.91828 32.7513 8.78449 32.8833 8.6014C33.0154 8.41831 33.0867 8.19578 33.0867 7.96709C33.0867 7.73841 33.0154 7.51587 32.8833 7.33278C32.7513 7.1497 32.5657 7.0159 32.3543 6.95143L27.9321 5.60059L26.6294 1.01027C26.5673 0.790829 26.4383 0.598168 26.2619 0.461118C26.0855 0.324068 25.871 0.25 25.6506 0.25C25.4303 0.25 25.2158 0.324068 25.0394 0.461118C24.8629 0.598168 24.734 0.790829 24.6719 1.01027L23.3702 5.60059L18.9471 6.95143C18.7357 7.01588 18.55 7.14966 18.418 7.33275C18.2859 7.51584 18.2146 7.73839 18.2146 7.96709C18.2146 8.19579 18.2859 8.41834 18.418 8.60143C18.55 8.78452 18.7357 8.91831 18.9471 8.98276L23.3702 10.3346L24.6719 14.9239C24.734 15.1434 24.8629 15.336 25.0394 15.4731C25.2158 15.6101 25.4303 15.6842 25.6506 15.6842C25.871 15.6842 26.0855 15.6101 26.2619 15.4731C26.4383 15.336 26.5673 15.1434 26.6294 14.9239L27.9321 10.3346Z"
fill="#7042F0" />
<path
d="M5.49703 12.2565L1.03503 14.1451C0.847305 14.2246 0.686661 14.3603 0.573578 14.535C0.460491 14.7096 0.400097 14.9152 0.400097 15.1256C0.400097 15.336 0.460491 15.5417 0.573578 15.7163C0.686661 15.8909 0.847305 16.0267 1.03503 16.1061L5.49703 17.9948L7.31694 22.6255C7.39355 22.8203 7.52433 22.987 7.69262 23.1043C7.8609 23.2217 8.05905 23.2844 8.2618 23.2844C8.46454 23.2844 8.66269 23.2217 8.83098 23.1043C8.99926 22.987 9.13005 22.8203 9.20666 22.6255L11.0266 17.9948L15.4876 16.1061C15.6754 16.0266 15.836 15.8909 15.9491 15.7163C16.0622 15.5417 16.1225 15.336 16.1225 15.1256C16.1225 14.9152 16.0622 14.7096 15.9491 14.535C15.836 14.3603 15.6754 14.2246 15.4876 14.1451L11.0266 12.2565L9.20666 7.62684C9.13005 7.43204 8.99926 7.26532 8.83098 7.14797C8.66269 7.03062 8.46454 6.96795 8.2618 6.96795C8.05905 6.96795 7.8609 7.03062 7.69262 7.14797C7.52433 7.26532 7.39355 7.43204 7.31694 7.62684L5.49703 12.2565Z"
fill="#7042F0" />
</svg>
</div>
<span
><strong>Auto-Generate</strong> an Image based on the content created within the
block editor.

<p-button
[style]="{
'background-color': 'white',
color: '#426BF0',
height: 'unset',
width: 'unset',
padding: '0',
margin: '0',
outline: 'none'
}"
tooltipZIndex="999999"
icon="pi pi-info-circle"
pTooltip="Describe the size, color palette, style, mood, etc."
tooltipPosition="top">
</p-button>
</span>

<form *ngIf="showFormTwo" [formGroup]="form" (ngSubmit)="onSubmit()" autocomplete="off">
<div class="input-field-wrapper">
<textarea
class="input-field"
placeholder="E.g. 1200x800px, vibrant colors, impressionistic, adventurous."
formControlName="promptAutoGenerate"></textarea>
</div>

<div class="submit-btn-container">
<p-button icon="pi pi-send" type="submit" label="Auto Generate"> </p-button>
</div>
</form>
</div>
</div>
</div>
Loading

0 comments on commit 5bd7635

Please sign in to comment.