@dataclouder/ngx-agent-cards 0.0.75 → 0.0.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -81,7 +81,7 @@ export abstract class AgentCardsAbstractService {
81
81
 
82
82
  ![Component Diagram](./docs/componentes_diagram.jpg)
83
83
 
84
- - **ConversationCardListsComponent**: Connects with backends shows availible conversations.
84
+ - **AgentCardListComponent**: Connects with backends shows availible conversations.
85
85
 
86
86
  - **DcAgentCardDetailsComponent**: Visualize Conversation Card details and start a conversation.
87
87
 
@@ -12,7 +12,7 @@ import { SkeletonModule } from 'primeng/skeleton';
12
12
  import * as i6$1 from 'primeng/dialog';
13
13
  import { DialogModule } from 'primeng/dialog';
14
14
  import * as i9 from '@dataclouder/ngx-core';
15
- import { TOAST_ALERTS_TOKEN, PaginationBase, DCFilterBarComponent } from '@dataclouder/ngx-core';
15
+ import { TOAST_ALERTS_TOKEN, PaginationBase, DCFilterBarComponent, QuickTableComponent } from '@dataclouder/ngx-core';
16
16
  import { DCMicComponent } from '@dataclouder/ngx-mic';
17
17
  import * as i7$2 from 'primeng/progressbar';
18
18
  import { ProgressBarModule } from 'primeng/progressbar';
@@ -2196,11 +2196,14 @@ class DCAgentCardFormComponent {
2196
2196
  this.dialogService = dialogService;
2197
2197
  this.promptBuilder = promptBuilder;
2198
2198
  this.toastService = toastService;
2199
+ // select options
2199
2200
  this.textEngines = Object.values(TextEngines);
2200
2201
  this.conversationOptions = ConversationTypeOptions;
2201
2202
  this.voiceTTSOptions = Object.values(VoiceTTSOptions);
2202
- this.agentCardId = this.activatedRoute.snapshot.paramMap.get('id');
2203
+ this.textEngineOptions = TextEngineOptions;
2203
2204
  this.accountsOptions = Object.values(EAccountsPlatform);
2205
+ this.languageOptions = Object.entries(LangCodeDescriptionEs).map(([value, label]) => ({ value, label }));
2206
+ this.agentCardId = this.activatedRoute.snapshot.paramMap.get('id');
2204
2207
  this.storageSettings = this.getSettings();
2205
2208
  this.bannerImgSettings = {
2206
2209
  path: 'conversation-cards/' + this.agentCardId,
@@ -2221,10 +2224,7 @@ class DCAgentCardFormComponent {
2221
2224
  this.onSave = new EventEmitter();
2222
2225
  this.onGoDetails = new EventEmitter();
2223
2226
  this.onTranslate = new EventEmitter();
2224
- this.textEngineOptions = TextEngineOptions;
2225
- this.markdownForm = this.fb.group({
2226
- seeMarkdown: [false],
2227
- });
2227
+ this.markdownForm = this.fb.group({ seeMarkdown: [false] });
2228
2228
  // Type is IAgentCard
2229
2229
  this.form = this.fb.group({
2230
2230
  version: ['1.0'],
@@ -2255,10 +2255,6 @@ class DCAgentCardFormComponent {
2255
2255
  model: this.fb.group({ id: [''], modelName: [''], provider: [''] }),
2256
2256
  accounts: this.fb.array([]),
2257
2257
  });
2258
- this.languageOptions = Object.entries(LangCodeDescriptionEs).map(([value, label]) => ({
2259
- value,
2260
- label,
2261
- }));
2262
2258
  this.isGenerating = false;
2263
2259
  }
2264
2260
  ngOnInit() {
@@ -2355,6 +2351,7 @@ class DCAgentCardFormComponent {
2355
2351
  }
2356
2352
  async saveConversation() {
2357
2353
  if (this.form.valid) {
2354
+ console.log(this.form.value);
2358
2355
  const data = { ...this.form.value, _id: this.agentCardId };
2359
2356
  const result = await this.agentCardService.saveConversationCard(data);
2360
2357
  console.log('data was saved', result);
@@ -2593,7 +2590,7 @@ class DCAgentCardFormComponent {
2593
2590
  this.cdr.detectChanges();
2594
2591
  }
2595
2592
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.1", ngImport: i0, type: DCAgentCardFormComponent, deps: [{ token: i1$1.FormBuilder }, { token: i2$2.MultiImagesStorageService }, { token: CONVERSATION_AI_TOKEN }, { token: i0.ChangeDetectorRef }, { token: i1$3.Router }, { token: i1$3.ActivatedRoute }, { token: i1$2.DialogService }, { token: DCConversationPromptBuilderService }, { token: TOAST_ALERTS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
2596
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.1", type: DCAgentCardFormComponent, isStandalone: true, selector: "dc-conversation-form", inputs: { storageSettings: "storageSettings", bannerImgSettings: "bannerImgSettings", imageStorageSettings: "imageStorageSettings" }, outputs: { onImageLoaded: "onImageLoaded", onSave: "onSave", onGoDetails: "onGoDetails", onTranslate: "onTranslate" }, providers: [DialogService], ngImport: i0, template: "<div class=\"top-buttons\">\n <button pButton severity=\"info\" (click)=\"checkPrompt()\" label=\"\uD83D\uDC41\uFE0F Ver instrucciones finales \uD83D\uDCD3\"></button>\n\n <button pButton severity=\"info\" (click)=\"goToDetails()\" label=\"\uD83D\uDCAC Conversar\"></button>\n <button pButton severity=\"primary\" (click)=\"saveConversation()\" label=\"\uD83D\uDCBE Guardar cambios\"></button>\n</div>\n\n<div class=\"top-buttons\">\n <p-button severity=\"help\" (click)=\"translate()\" label=\"\uD83D\uDD04 Traducir\"></p-button>\n <p-button [loading]=\"isGenerating\" severity=\"help\" (click)=\"generateCharacter()\" label=\"Generar \uD83E\uDDBE\"></p-button>\n\n <p-button severity=\"info\" (click)=\"downloadConversation()\" label=\"\uD83D\uDCC1 Exportar \u2B07\uFE0F\"></p-button>\n <p-button severity=\"info\" (click)=\"importConversation()\" label=\"\uD83C\uDCCF Importar \u2B06\uFE0F\"></p-button>\n</div>\n\n<br />\n<br />\n<form [formGroup]=\"form\" class=\"conversation-form\">\n <div class=\"form-grid\">\n <div class=\"left-column\">\n <div style=\"display: flex; gap: 15px\">\n <div class=\"form-field\">\n <label for=\"version\">Version: {{ form.controls.version.value }} <span pTooltip=\"Version number of the conversation\">\u2139\uFE0F</span></label>\n </div>\n\n <div class=\"form-field\">\n <label for=\"id\"\n >ID: <span pTooltip=\"Unique identifier for this conversation\"> {{ form.controls.id.value }} \u2139\uFE0F</span></label\n >\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"title\">Title <span pTooltip=\"T\u00EDtulo de la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <input pInputText id=\"title\" type=\"text\" formControlName=\"title\" />\n @if(form.controls.title.errors?.['required'] && form.controls.title.touched){\n <div class=\"error\"> Title is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n formControlName=\"lang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div formGroupName=\"conversationSettings\" class=\"group\">\n <h3>Conversation Settings <span pTooltip=\"Additional information about the conversation\">\u2139\uFE0F</span></h3>\n\n <div class=\"form-field\">\n <label for=\"textEngine\">\n Text Engine\n <span\n class=\"cursor-pointer\"\n (click)=\"textEngineDialog.toggle($event)\"\n pTooltip=\"Sistema de generaci\u00F3n de texto y audios. Client: el cliente llama al servidor en cada dialogo de voz/personaje, es optimo para historias, Server SSML: se sintetiza todo el audio en uno solo con los distintos cambios de voz/personaje, util para la reflexi\u00F3n porque es bilingue, utiliza dialogos en ingles y espa\u00F1ol en el mismo dialogo/audio\"\n >\u2139\uFE0F</span\n >\n </label>\n\n <p-select\n id=\"textEngine\"\n [options]=\"textEngineOptions\"\n formControlName=\"textEngine\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Text Engine'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"conversationType\">Conversation Type <span pTooltip=\"Choose the type of conversation interaction\">\u2139\uFE0F</span></label>\n <p-select\n id=\"conversationType\"\n [options]=\"conversationOptions\"\n formControlName=\"conversationType\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Conversation Type'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label> Auto Start <span pTooltip=\"Start conversation automatically\">\u2139\uFE0F</span> </label>\n <p-toggleSwitch formControlName=\"autoStart\"> </p-toggleSwitch>\n </div>\n </div>\n\n <div formGroupName=\"tts\" class=\"group\">\n <h3>TTS Settings <span pTooltip=\"Text-to-Speech configuration options\">\u2139\uFE0F</span></h3>\n\n <div class=\"form-field\">\n <label for=\"voice\">Voice <span pTooltip=\"Select the primary voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-select\n id=\"voice\"\n [options]=\"voiceTTSOptions\"\n formControlName=\"voice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Voice'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"secondaryVoice\">Secondary Voice <span pTooltip=\"Select an alternative voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-select\n id=\"secondaryVoice\"\n [options]=\"voiceTTSOptions\"\n formControlName=\"secondaryVoice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Secondary Voice'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"speed\">Speed <span pTooltip=\"Set the speech rate for text-to-speech conversion\">\u2139\uFE0F</span></label>\n <input pInputText id=\"speed\" type=\"text\" formControlName=\"speed\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"speedRate\">Speed Rate <span pTooltip=\"Adjust the rate of speech delivery\">\u2139\uFE0F</span></label>\n <input pInputText id=\"speedRate\" type=\"number\" formControlName=\"speedRate\" step=\"0.1\" />\n </div>\n </div>\n\n <div formGroupName=\"metaApp\" class=\"group\">\n <h3>Meta Information <span pTooltip=\"Additional information about the conversation\">\u2139\uFE0F</span></h3>\n <div class=\"form-field\">\n <label for=\"authorId\">Author ID <span pTooltip=\"Unique identifier for the conversation author\">\u2139\uFE0F</span></label>\n <input pInputText id=\"authorId\" type=\"text\" formControlName=\"authorId\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"authorEmail\">Author Email \u2139\uFE0F</label>\n <input pInputText id=\"authorEmail\" type=\"email\" formControlName=\"authorEmail\" />\n <div class=\"error\" *ngIf=\"form.get('metaApp.authorEmail')?.errors?.['email'] && form.get('metaApp.authorEmail')?.touched\">\n Please enter a valid email address\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"takenCount\"\n >Taken Count <span pTooltip=\"Es el contador de cuantas veces se ha tomado esta conversaci\u00F3n, no sirve por ahora\"> \u2139\uFE0F</span></label\n >\n <input pInputText id=\"takenCount\" type=\"number\" formControlName=\"takenCount\" />\n </div>\n\n <div class=\"form-field checkbox\">\n <label>\n <p-checkbox [binary]=\"true\" formControlName=\"isPublic\" />\n Public\n </label>\n </div>\n\n <div class=\"form-field checkbox\">\n <label>\n <p-checkbox [binary]=\"true\" formControlName=\"isPublished\" />\n Published\n </label>\n </div>\n </div>\n\n <div class=\"group\">\n <h4>Model Settings <span pTooltip=\"AI model configuration\">\u2139\uFE0F</span></h4>\n\n <dc-provider-selector [parentForm]=\"form.controls.model\"></dc-provider-selector>\n </div>\n\n <div class=\"group\">\n <h4>Gestion de cuentas</h4>\n <account-platform-form [formArray]=\"form.controls.accounts\"></account-platform-form>\n </div>\n </div>\n\n <div class=\"right-column\">\n <div style=\"position: relative; min-height: 60px\">\n @if (conversation?.assets?.bannerImg?.url) {\n <img [src]=\"conversation.assets.bannerImg.url\" class=\"main-banner-image-card\" />\n } @if(agentCardId) {\n\n <dc-cropper-modal\n style=\"position: absolute; bottom: 10px; right: 10px\"\n #cropperBanner\n id=\"cropperBanner\"\n [buttonLabel]=\"conversation?.assets?.bannerImg?.url ? 'Cambiar el banner' : 'Cargar un banner'\"\n [imgStorageSettings]=\"bannerImgSettings\"\n [currentStorage]=\"conversation?.assets?.bannerImg\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'bannerImg')\"></dc-cropper-modal>\n\n }\n </div>\n <div style=\"position: relative\">\n @if (conversation?.assets?.image?.url) {\n\n <img [src]=\"conversation.assets.image.url\" class=\"main-image-card\" />\n } @if (!agentCardId) {\n <button pButton (click)=\"saveConversation()\"> Guarda el scenario para subir la imagen</button>\n } @else {\n\n <dc-cropper-modal\n style=\"position: absolute; bottom: 10px; left: 50%\"\n id=\"cropperCardImage\"\n #cropperCardImage\n [buttonLabel]=\"conversation?.assets?.image?.url ? 'Cambiar imagen' : 'Cargar una imagen'\"\n [imgStorageSettings]=\"imageStorageSettings\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'image')\"></dc-cropper-modal>\n }\n </div>\n\n <div>\n <h4>Agregar stickers</h4>\n\n <dc-cropper-modal\n id=\"cropperCardImage\"\n #cropperStickers\n [buttonLabel]=\"'agregar sticker'\"\n [imgStorageSettings]=\"stickerStorageSettings\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'sticker')\"></dc-cropper-modal>\n </div>\n\n <div style=\"display: flex; flex-wrap: wrap; gap: 10px\">\n @for (sticker of conversation?.assets?.stickers; track sticker.url) {\n <div style=\"position: relative\">\n <img width=\"100\" [src]=\"sticker.url\" alt=\"\" />\n <p-button (click)=\"removeSticker(sticker)\" class=\"remove-sticker\" icon=\"pi pi-times\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\" />\n </div>\n }\n </div>\n\n <!-- <input pInputText type=\"file\" accept=\"image/*\" (change)=\"onImageSelected($event)\" /> -->\n\n <div formGroupName=\"characterCard\">\n <div formGroupName=\"data\" class=\"card-group\">\n <h3>Character Card <span pTooltip=\"Informaci\u00F3n de la ficha del personaje\">\u2139\uFE0F</span></h3>\n <div class=\"form-field\">\n <label for=\"cardName\">Name <span pTooltip=\"El nombre del personaje\">\u2139\uFE0F</span></label>\n <input pInputText id=\"cardName\" type=\"text\" formControlName=\"name\" />\n <div class=\"error\" *ngIf=\"form.get('characterCard.data.name')?.errors?.['required'] && form.get('characterCard.data.name')?.touched\">\n Name is required\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardDescription\">Description <span pTooltip=\"Descripci\u00F3n detallada del personaje\">\u2139\uFE0F</span></label>\n <textarea class=\"textmin\" rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardDescription\" formControlName=\"description\"></textarea>\n <div class=\"error\" *ngIf=\"form.get('characterCard.data.description')?.errors?.['required'] && form.get('characterCard.data.description')?.touched\">\n Description is required\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardScenario\">Scenario <span pTooltip=\"Describe the context or setting for the conversation\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardScenario\" formControlName=\"scenario\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardFirstMessage\">\n First Message\n <span pTooltip=\"Es muy importante que la historia inicie bien, ya que es el patr\u00F3n inicial para la AI, respetar las convenciones de texto\"\n >\u2139\uFE0F</span\n >\n\n <p-togglebutton\n [formControl]=\"markdownForm.controls.seeMarkdown\"\n [onLabel]=\"'Editar'\"\n [offLabel]=\"'Ver Markdown Texto'\"\n size=\"small\"\n styleClass=\"min-w-16\"\n (onChange)=\"checkCdr()\" />\n </label>\n\n @if(markdownForm.controls.seeMarkdown.value){\n <div [innerHTML]=\"form.controls.characterCard.controls.data.controls.first_mes.value | mdToHtmlArray\"></div>\n }@else{\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardFirstMessage\" formControlName=\"first_mes\"> </textarea>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"mes_example\">Mensajes de Ejemplo <span pTooltip=\"Importante para el estilo de la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"mes_example\" formControlName=\"mes_example\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardCreatorNotes\">Creator Notes <span pTooltip=\"son solo notas del creador, no afecta nada a la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardCreatorNotes\" formControlName=\"creator_notes\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardSystemPrompt\">System Prompt (Opcional) <span pTooltip=\"Instrucciones del sistema para la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardSystemPrompt\" formControlName=\"system_prompt\"></textarea>\n <div\n class=\"error\"\n *ngIf=\"form.get('characterCard.data.system_prompt')?.errors?.['required'] && form.get('characterCard.data.system_prompt')?.touched\">\n System prompt is required\n </div>\n </div>\n\n <div style=\"display: flex; flex-direction: column\">\n <label for=\"cardPostHistoryInstructions\"\n >Post-History Instructions (Opcional)\n <span\n pTooltip=\"Dejar en blanco, al menos que se sepa como funciona, esto se llama jailbreak, es para darle instrucciones finales y m\u00E1s importantes al modelo\"\n >\u2139\uFE0F</span\n ></label\n >\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" formControlName=\"post_history_instructions\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardAlternateGreetings\">Alternate Greetings <span pTooltip=\"Saludos alternativos para comenzar una historia diferente\">\u2139\uFE0F</span></label>\n <div class=\"array-field\">\n <div\n *ngFor=\"let greeting of form.controls.characterCard.controls.data.controls.alternate_greetings.controls; let i = index\"\n class=\"array-item\"\n style=\"position: relative\">\n <textarea\n pTextarea\n rows=\"1\"\n [autoResize]=\"true\"\n [id]=\"'cardAlternateGreeting' + i\"\n [formControl]=\"greeting\"\n (input)=\"updateArrayField('alternate_greetings', i, $event)\">\n </textarea>\n <button pButton severity=\"danger\" class=\"remove-button\" (click)=\"removeArrayItem('alternate_greetings', i)\">&#x2716;</button>\n </div>\n <button pButton severity=\"info\" (click)=\"addArrayItem('alternate_greetings')\">Add Greeting</button>\n </div>\n </div>\n\n <div class=\"form-field\">\n <label pTooltip=\"Agrega las categorias\" for=\"cardTags\">Tags \u2139\uFE0F</label>\n <div class=\"array-field\">\n <div *ngFor=\"let tag of form.controls.characterCard.controls.data.controls.tags.controls; let i = index\" class=\"array-item\">\n <input [id]=\"'cardTag' + i\" type=\"text\" [formControl]=\"tag\" (input)=\"updateArrayField('tags', i, $event)\" />\n <button pButton severity=\"danger\" (click)=\"removeArrayItem('tags', i)\">Remove</button>\n </div>\n <button pButton severity=\"info\" (click)=\"addArrayItem('tags')\">Add Tag</button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</form>\n\n<p-popover #textEngineDialog header=\"Text Engine Information\">\n <div class=\"p-4\">\n <h3>Text Engine Types</h3>\n <ul>\n <li> <strong>Texto Simple</strong> La conversaci\u00F3n es como chatgpt, preguntas y responde, es la m\u00E1s b\u00E1sica</li>\n\n <li\n ><strong>Multi Mensajes</strong> Utiliza markdown (recomendable entenderlo), sirve para darle formato al texto y sea m\u00E1s agradable de leer, el sistema\n puede partir dialogos que tienen distinto formato, como normal, cursiva y negritas, asi puede generar distintas voces y estilo para el narrador y\n personaje principal</li\n >\n <li\n ><strong>MD SSML :</strong> Markdown con Lenguaje de marcaci\u00F3n de s\u00EDntesis de voz (SSML), es tambien markdown pero a diferencia de multimessage, solo se\n presenta un mensaje. y la voz se genera para toda la linea,normalmente lo uso para conversaciones bilingues.</li\n >\n </ul>\n </div>\n</p-popover>\n\n<div class=\"float-button\">\n <p-button icon=\"pi pi-save\" (click)=\"saveConversation()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n</div>\n", styles: [".textmin{min-width:36vw}.main-image-card{max-width:280px;display:block;margin:0 auto;border-radius:8px}.main-banner-image-card{border-radius:8px}.remove-sticker{position:absolute;top:5px;right:5px}.conversation-form{max-width:100%;padding:20px;background-color:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a}.conversation-form .card-group{background-color:#f8f9fa;padding:20px;border-radius:6px;margin-bottom:24px}.conversation-form .card-group h3{margin:0 0 20px;color:#2c3e50;font-size:1.25rem}.conversation-form .form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:2rem;width:100%;max-width:100%}@media (max-width: 768px){.conversation-form .form-grid{grid-template-columns:1fr}}.conversation-form .form-field{margin-bottom:1.5rem;display:flex;flex-direction:column;gap:.5rem}.conversation-form .form-field label{font-weight:500}.conversation-form .form-field textarea{resize:vertical}.conversation-form .form-field.checkbox{flex-direction:row;align-items:center;gap:.5rem}.conversation-form .form-field.checkbox input[type=checkbox]{width:auto}.conversation-form .form-field .error{color:#dc3545;font-size:.875rem;margin-top:.25rem}.conversation-form .form-field .remove-button{position:absolute;border:none;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;cursor:pointer;top:-10px;right:-10px}.conversation-form .left-column,.conversation-form .right-column{display:flex;flex-direction:column;gap:1rem}.conversation-form .array-field{display:flex;flex-direction:column;gap:.5rem}.conversation-form .array-field .array-item{display:flex;gap:.5rem}.conversation-form .array-field .array-item input,.conversation-form .array-field .array-item textarea{flex:1}.conversation-form .array-field .array-item button{padding:.5rem}.conversation-form .array-field button[type=button]{background-color:#28a745;color:#fff;border:none;padding:8px 12px;border-radius:4px;cursor:pointer;transition:background-color .2s}.conversation-form .array-field button[type=button]:hover{background-color:#218838}.conversation-form .group,.conversation-form .meta-group,.conversation-form .card-group{background-color:#f8f9fa;padding:1rem;border-radius:4px;margin-bottom:1.5rem}.conversation-form .group h3,.conversation-form .meta-group h3,.conversation-form .card-group h3{margin-top:0;margin-bottom:1rem}.top-buttons{display:flex;justify-content:space-between;margin-bottom:2rem;gap:1rem}.top-buttons button{flex:1}::ng-deep em{font-weight:900;color:#014a93}.float-button{position:fixed;bottom:4rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: CropperComponentModal, selector: "dc-cropper-modal", inputs: ["imgStorageSettings", "buttonLabel", "currentStorage"], outputs: ["imageUploaded", "onImageCropped", "onFileSelected"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "ngmodule", type: PortalModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i7$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: i7$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i8$1.Textarea, selector: "[pTextarea]", inputs: ["autoResize", "variant", "fluid", "pSize"], outputs: ["onResize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i5$1.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "name", "disabled", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "inputStyle", "styleClass", "inputClass", "indeterminate", "size", "formControl", "checkboxIcon", "readonly", "required", "autofocus", "trueValue", "falseValue", "variant"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToggleButtonModule }, { kind: "component", type: i11.ToggleButton, selector: "p-toggleButton, p-togglebutton, p-toggle-button", inputs: ["onLabel", "offLabel", "onIcon", "offIcon", "ariaLabel", "ariaLabelledBy", "disabled", "style", "styleClass", "inputId", "tabindex", "size", "iconPos", "autofocus", "allowEmpty"], outputs: ["onChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i7.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i13.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["style", "styleClass", "tabindex", "inputId", "name", "disabled", "readonly", "trueValue", "falseValue", "ariaLabel", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "pipe", type: MdToHtmlArrayPipe, name: "mdToHtmlArray" }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i14.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "size", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "fluid", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i15.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: ProviderSelectorComponent, selector: "dc-provider-selector", inputs: ["parentForm"] }, { kind: "component", type: AccountPlatformForm, selector: "account-platform-form", inputs: ["formArray"] }] }); }
2593
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.1", type: DCAgentCardFormComponent, isStandalone: true, selector: "dc-conversation-form", inputs: { storageSettings: "storageSettings", bannerImgSettings: "bannerImgSettings", imageStorageSettings: "imageStorageSettings" }, outputs: { onImageLoaded: "onImageLoaded", onSave: "onSave", onGoDetails: "onGoDetails", onTranslate: "onTranslate" }, providers: [DialogService], ngImport: i0, template: "<div class=\"top-buttons\">\n <button pButton severity=\"info\" (click)=\"checkPrompt()\" label=\"\uD83D\uDC41\uFE0F Ver instrucciones finales \uD83D\uDCD3\"></button>\n\n <button pButton severity=\"info\" (click)=\"goToDetails()\" label=\"\uD83D\uDCAC Conversar\"></button>\n <button pButton severity=\"primary\" (click)=\"saveConversation()\" label=\"\uD83D\uDCBE Guardar cambios\"></button>\n</div>\n\n<div class=\"top-buttons\">\n <p-button severity=\"help\" (click)=\"translate()\" label=\"\uD83D\uDD04 Traducir\"></p-button>\n <p-button [loading]=\"isGenerating\" severity=\"help\" (click)=\"generateCharacter()\" label=\"Generar \uD83E\uDDBE\"></p-button>\n\n <p-button severity=\"info\" (click)=\"downloadConversation()\" label=\"\uD83D\uDCC1 Exportar \u2B07\uFE0F\"></p-button>\n <p-button severity=\"info\" (click)=\"importConversation()\" label=\"\uD83C\uDCCF Importar \u2B06\uFE0F\"></p-button>\n</div>\n\n<br />\n<br />\n<form [formGroup]=\"form\" class=\"conversation-form\">\n <div class=\"form-grid\">\n <div class=\"left-column\">\n <div style=\"display: flex; gap: 15px\">\n <div class=\"form-field\">\n <label for=\"version\">Version: {{ form.controls.version.value }} <span pTooltip=\"Version number of the conversation\">\u2139\uFE0F</span></label>\n </div>\n\n <div class=\"form-field\">\n <label for=\"id\"\n >ID: <span pTooltip=\"Unique identifier for this conversation\"> {{ form.controls.id.value }} \u2139\uFE0F</span></label\n >\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"title\">Title <span pTooltip=\"T\u00EDtulo de la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <input pInputText id=\"title\" type=\"text\" formControlName=\"title\" />\n @if(form.controls.title.errors?.['required'] && form.controls.title.touched){\n <div class=\"error\"> Title is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n formControlName=\"lang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div formGroupName=\"conversationSettings\" class=\"group\">\n <h3>Conversation Settings <span pTooltip=\"Additional information about the conversation\">\u2139\uFE0F</span></h3>\n\n <div class=\"form-field\">\n <label for=\"textEngine\">\n Text Engine\n <span\n class=\"cursor-pointer\"\n (click)=\"textEngineDialog.toggle($event)\"\n pTooltip=\"Sistema de generaci\u00F3n de texto y audios. Client: el cliente llama al servidor en cada dialogo de voz/personaje, es optimo para historias, Server SSML: se sintetiza todo el audio en uno solo con los distintos cambios de voz/personaje, util para la reflexi\u00F3n porque es bilingue, utiliza dialogos en ingles y espa\u00F1ol en el mismo dialogo/audio\"\n >\u2139\uFE0F</span\n >\n </label>\n\n <p-select\n id=\"textEngine\"\n [options]=\"textEngineOptions\"\n formControlName=\"textEngine\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Text Engine'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"conversationType\">Conversation Type <span pTooltip=\"Choose the type of conversation interaction\">\u2139\uFE0F</span></label>\n <p-select\n id=\"conversationType\"\n [options]=\"conversationOptions\"\n formControlName=\"conversationType\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Conversation Type'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label> Auto Start <span pTooltip=\"Start conversation automatically\">\u2139\uFE0F</span> </label>\n <p-toggleSwitch formControlName=\"autoStart\"> </p-toggleSwitch>\n </div>\n </div>\n\n <div formGroupName=\"tts\" class=\"group\">\n <h3>TTS Settings <span pTooltip=\"Text-to-Speech configuration options\">\u2139\uFE0F</span></h3>\n\n <div class=\"form-field\">\n <label for=\"voice\">Voice <span pTooltip=\"Select the primary voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-select\n id=\"voice\"\n [options]=\"voiceTTSOptions\"\n formControlName=\"voice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Voice'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"secondaryVoice\">Secondary Voice <span pTooltip=\"Select an alternative voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-select\n id=\"secondaryVoice\"\n [options]=\"voiceTTSOptions\"\n formControlName=\"secondaryVoice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Secondary Voice'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"speed\">Speed <span pTooltip=\"Set the speech rate for text-to-speech conversion\">\u2139\uFE0F</span></label>\n <input pInputText id=\"speed\" type=\"text\" formControlName=\"speed\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"speedRate\">Speed Rate <span pTooltip=\"Adjust the rate of speech delivery\">\u2139\uFE0F</span></label>\n <input pInputText id=\"speedRate\" type=\"number\" formControlName=\"speedRate\" step=\"0.1\" />\n </div>\n </div>\n\n <div formGroupName=\"metaApp\" class=\"group\">\n <h3>Meta Information <span pTooltip=\"Additional information about the conversation\">\u2139\uFE0F</span></h3>\n <div class=\"form-field\">\n <label for=\"authorId\">Author ID <span pTooltip=\"Unique identifier for the conversation author\">\u2139\uFE0F</span></label>\n <input pInputText id=\"authorId\" type=\"text\" formControlName=\"authorId\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"authorEmail\">Author Email \u2139\uFE0F</label>\n <input pInputText id=\"authorEmail\" type=\"email\" formControlName=\"authorEmail\" />\n <div class=\"error\" *ngIf=\"form.get('metaApp.authorEmail')?.errors?.['email'] && form.get('metaApp.authorEmail')?.touched\">\n Please enter a valid email address\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"takenCount\"\n >Taken Count <span pTooltip=\"Es el contador de cuantas veces se ha tomado esta conversaci\u00F3n, no sirve por ahora\"> \u2139\uFE0F</span></label\n >\n <input pInputText id=\"takenCount\" type=\"number\" formControlName=\"takenCount\" />\n </div>\n\n <div class=\"form-field checkbox\">\n <label>\n <p-checkbox [binary]=\"true\" formControlName=\"isPublic\" />\n Public\n </label>\n </div>\n\n <div class=\"form-field checkbox\">\n <label>\n <p-checkbox [binary]=\"true\" formControlName=\"isPublished\" />\n Published\n </label>\n </div>\n </div>\n\n <div class=\"group\">\n <h4>Model Settings <span pTooltip=\"AI model configuration\">\u2139\uFE0F</span></h4>\n\n <dc-provider-selector [parentForm]=\"form.controls.model\"></dc-provider-selector>\n </div>\n\n <div class=\"group\">\n <h4>Gestion de cuentas</h4>\n @if(form.controls.accounts){\n <account-platform-form [formArray]=\"form.controls.accounts\"></account-platform-form>\n\n }\n </div>\n </div>\n\n <div class=\"right-column\">\n <div style=\"position: relative; min-height: 60px\">\n @if (conversation?.assets?.bannerImg?.url) {\n <img [src]=\"conversation.assets.bannerImg.url\" class=\"main-banner-image-card\" />\n } @if(agentCardId) {\n\n <dc-cropper-modal\n style=\"position: absolute; bottom: 10px; right: 10px\"\n #cropperBanner\n id=\"cropperBanner\"\n [buttonLabel]=\"conversation?.assets?.bannerImg?.url ? 'Cambiar el banner' : 'Cargar un banner'\"\n [imgStorageSettings]=\"bannerImgSettings\"\n [currentStorage]=\"conversation?.assets?.bannerImg\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'bannerImg')\"></dc-cropper-modal>\n\n }\n </div>\n <div style=\"position: relative\">\n @if (conversation?.assets?.image?.url) {\n\n <img [src]=\"conversation.assets.image.url\" class=\"main-image-card\" />\n } @if (!agentCardId) {\n <button pButton (click)=\"saveConversation()\"> Guarda el scenario para subir la imagen</button>\n } @else {\n\n <dc-cropper-modal\n style=\"position: absolute; bottom: 10px; left: 50%\"\n id=\"cropperCardImage\"\n #cropperCardImage\n [buttonLabel]=\"conversation?.assets?.image?.url ? 'Cambiar imagen' : 'Cargar una imagen'\"\n [imgStorageSettings]=\"imageStorageSettings\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'image')\"></dc-cropper-modal>\n }\n </div>\n\n <div>\n <h4>Agregar stickers</h4>\n\n <dc-cropper-modal\n id=\"cropperCardImage\"\n #cropperStickers\n [buttonLabel]=\"'agregar sticker'\"\n [imgStorageSettings]=\"stickerStorageSettings\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'sticker')\"></dc-cropper-modal>\n </div>\n\n <div style=\"display: flex; flex-wrap: wrap; gap: 10px\">\n @for (sticker of conversation?.assets?.stickers; track sticker.url) {\n <div style=\"position: relative\">\n <img width=\"100\" [src]=\"sticker.url\" alt=\"\" />\n <p-button (click)=\"removeSticker(sticker)\" class=\"remove-sticker\" icon=\"pi pi-times\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\" />\n </div>\n }\n </div>\n\n <!-- <input pInputText type=\"file\" accept=\"image/*\" (change)=\"onImageSelected($event)\" /> -->\n\n <div formGroupName=\"characterCard\">\n <div formGroupName=\"data\" class=\"card-group\">\n <h3>Character Card <span pTooltip=\"Informaci\u00F3n de la ficha del personaje\">\u2139\uFE0F</span></h3>\n <div class=\"form-field\">\n <label for=\"cardName\">Name <span pTooltip=\"El nombre del personaje\">\u2139\uFE0F</span></label>\n <input pInputText id=\"cardName\" type=\"text\" formControlName=\"name\" />\n <div class=\"error\" *ngIf=\"form.get('characterCard.data.name')?.errors?.['required'] && form.get('characterCard.data.name')?.touched\">\n Name is required\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardDescription\">Description <span pTooltip=\"Descripci\u00F3n detallada del personaje\">\u2139\uFE0F</span></label>\n <textarea class=\"textmin\" rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardDescription\" formControlName=\"description\"></textarea>\n <div class=\"error\" *ngIf=\"form.get('characterCard.data.description')?.errors?.['required'] && form.get('characterCard.data.description')?.touched\">\n Description is required\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardScenario\">Scenario <span pTooltip=\"Describe the context or setting for the conversation\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardScenario\" formControlName=\"scenario\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardFirstMessage\">\n First Message\n <span pTooltip=\"Es muy importante que la historia inicie bien, ya que es el patr\u00F3n inicial para la AI, respetar las convenciones de texto\"\n >\u2139\uFE0F</span\n >\n\n <p-togglebutton\n [formControl]=\"markdownForm.controls.seeMarkdown\"\n [onLabel]=\"'Editar'\"\n [offLabel]=\"'Ver Markdown Texto'\"\n size=\"small\"\n styleClass=\"min-w-16\"\n (onChange)=\"checkCdr()\" />\n </label>\n\n @if(markdownForm.controls.seeMarkdown.value){\n <div [innerHTML]=\"form.controls.characterCard.controls.data.controls.first_mes.value | mdToHtmlArray\"></div>\n }@else{\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardFirstMessage\" formControlName=\"first_mes\"> </textarea>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"mes_example\">Mensajes de Ejemplo <span pTooltip=\"Importante para el estilo de la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"mes_example\" formControlName=\"mes_example\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardCreatorNotes\">Creator Notes <span pTooltip=\"son solo notas del creador, no afecta nada a la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardCreatorNotes\" formControlName=\"creator_notes\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardSystemPrompt\">System Prompt (Opcional) <span pTooltip=\"Instrucciones del sistema para la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardSystemPrompt\" formControlName=\"system_prompt\"></textarea>\n <div\n class=\"error\"\n *ngIf=\"form.get('characterCard.data.system_prompt')?.errors?.['required'] && form.get('characterCard.data.system_prompt')?.touched\">\n System prompt is required\n </div>\n </div>\n\n <div style=\"display: flex; flex-direction: column\">\n <label for=\"cardPostHistoryInstructions\"\n >Post-History Instructions (Opcional)\n <span\n pTooltip=\"Dejar en blanco, al menos que se sepa como funciona, esto se llama jailbreak, es para darle instrucciones finales y m\u00E1s importantes al modelo\"\n >\u2139\uFE0F</span\n ></label\n >\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" formControlName=\"post_history_instructions\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardAlternateGreetings\">Alternate Greetings <span pTooltip=\"Saludos alternativos para comenzar una historia diferente\">\u2139\uFE0F</span></label>\n <div class=\"array-field\">\n <div\n *ngFor=\"let greeting of form.controls.characterCard.controls.data.controls.alternate_greetings.controls; let i = index\"\n class=\"array-item\"\n style=\"position: relative\">\n <textarea\n pTextarea\n rows=\"1\"\n [autoResize]=\"true\"\n [id]=\"'cardAlternateGreeting' + i\"\n [formControl]=\"greeting\"\n (input)=\"updateArrayField('alternate_greetings', i, $event)\">\n </textarea>\n <button pButton severity=\"danger\" class=\"remove-button\" (click)=\"removeArrayItem('alternate_greetings', i)\">&#x2716;</button>\n </div>\n <button pButton severity=\"info\" (click)=\"addArrayItem('alternate_greetings')\">Add Greeting</button>\n </div>\n </div>\n\n <div class=\"form-field\">\n <label pTooltip=\"Agrega las categorias\" for=\"cardTags\">Tags \u2139\uFE0F</label>\n <div class=\"array-field\">\n <div *ngFor=\"let tag of form.controls.characterCard.controls.data.controls.tags.controls; let i = index\" class=\"array-item\">\n <input [id]=\"'cardTag' + i\" type=\"text\" [formControl]=\"tag\" (input)=\"updateArrayField('tags', i, $event)\" />\n <button pButton severity=\"danger\" (click)=\"removeArrayItem('tags', i)\">Remove</button>\n </div>\n <button pButton severity=\"info\" (click)=\"addArrayItem('tags')\">Add Tag</button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</form>\n\n<p-popover #textEngineDialog header=\"Text Engine Information\">\n <div class=\"p-4\">\n <h3>Text Engine Types</h3>\n <ul>\n <li> <strong>Texto Simple</strong> La conversaci\u00F3n es como chatgpt, preguntas y responde, es la m\u00E1s b\u00E1sica</li>\n\n <li\n ><strong>Multi Mensajes</strong> Utiliza markdown (recomendable entenderlo), sirve para darle formato al texto y sea m\u00E1s agradable de leer, el sistema\n puede partir dialogos que tienen distinto formato, como normal, cursiva y negritas, asi puede generar distintas voces y estilo para el narrador y\n personaje principal</li\n >\n <li\n ><strong>MD SSML :</strong> Markdown con Lenguaje de marcaci\u00F3n de s\u00EDntesis de voz (SSML), es tambien markdown pero a diferencia de multimessage, solo se\n presenta un mensaje. y la voz se genera para toda la linea,normalmente lo uso para conversaciones bilingues.</li\n >\n </ul>\n </div>\n</p-popover>\n\n<div class=\"float-button\">\n <p-button icon=\"pi pi-save\" (click)=\"saveConversation()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n</div>\n", styles: [".textmin{min-width:36vw}.main-image-card{max-width:280px;display:block;margin:0 auto;border-radius:8px}.main-banner-image-card{border-radius:8px}.remove-sticker{position:absolute;top:5px;right:5px}.conversation-form{max-width:100%;padding:20px;background-color:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a}.conversation-form .card-group{background-color:#f8f9fa;padding:20px;border-radius:6px;margin-bottom:24px}.conversation-form .card-group h3{margin:0 0 20px;color:#2c3e50;font-size:1.25rem}.conversation-form .form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:2rem;width:100%;max-width:100%}@media (max-width: 768px){.conversation-form .form-grid{grid-template-columns:1fr}}.conversation-form .form-field{margin-bottom:1.5rem;display:flex;flex-direction:column;gap:.5rem}.conversation-form .form-field label{font-weight:500}.conversation-form .form-field textarea{resize:vertical}.conversation-form .form-field.checkbox{flex-direction:row;align-items:center;gap:.5rem}.conversation-form .form-field.checkbox input[type=checkbox]{width:auto}.conversation-form .form-field .error{color:#dc3545;font-size:.875rem;margin-top:.25rem}.conversation-form .form-field .remove-button{position:absolute;border:none;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;cursor:pointer;top:-10px;right:-10px}.conversation-form .left-column,.conversation-form .right-column{display:flex;flex-direction:column;gap:1rem}.conversation-form .array-field{display:flex;flex-direction:column;gap:.5rem}.conversation-form .array-field .array-item{display:flex;gap:.5rem}.conversation-form .array-field .array-item input,.conversation-form .array-field .array-item textarea{flex:1}.conversation-form .array-field .array-item button{padding:.5rem}.conversation-form .array-field button[type=button]{background-color:#28a745;color:#fff;border:none;padding:8px 12px;border-radius:4px;cursor:pointer;transition:background-color .2s}.conversation-form .array-field button[type=button]:hover{background-color:#218838}.conversation-form .group,.conversation-form .meta-group,.conversation-form .card-group{background-color:#f8f9fa;padding:1rem;border-radius:4px;margin-bottom:1.5rem}.conversation-form .group h3,.conversation-form .meta-group h3,.conversation-form .card-group h3{margin-top:0;margin-bottom:1rem}.top-buttons{display:flex;justify-content:space-between;margin-bottom:2rem;gap:1rem}.top-buttons button{flex:1}::ng-deep em{font-weight:900;color:#014a93}.float-button{position:fixed;bottom:4rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: CropperComponentModal, selector: "dc-cropper-modal", inputs: ["imgStorageSettings", "buttonLabel", "currentStorage"], outputs: ["imageUploaded", "onImageCropped", "onFileSelected"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "ngmodule", type: PortalModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i7$1.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: i7$1.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i8$1.Textarea, selector: "[pTextarea]", inputs: ["autoResize", "variant", "fluid", "pSize"], outputs: ["onResize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i5$1.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "name", "disabled", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "inputStyle", "styleClass", "inputClass", "indeterminate", "size", "formControl", "checkboxIcon", "readonly", "required", "autofocus", "trueValue", "falseValue", "variant"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToggleButtonModule }, { kind: "component", type: i11.ToggleButton, selector: "p-toggleButton, p-togglebutton, p-toggle-button", inputs: ["onLabel", "offLabel", "onIcon", "offIcon", "ariaLabel", "ariaLabelledBy", "disabled", "style", "styleClass", "inputId", "tabindex", "size", "iconPos", "autofocus", "allowEmpty"], outputs: ["onChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i7.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i13.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["style", "styleClass", "tabindex", "inputId", "name", "disabled", "readonly", "trueValue", "falseValue", "ariaLabel", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "pipe", type: MdToHtmlArrayPipe, name: "mdToHtmlArray" }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i14.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "size", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "fluid", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i15.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: ProviderSelectorComponent, selector: "dc-provider-selector", inputs: ["parentForm"] }, { kind: "component", type: AccountPlatformForm, selector: "account-platform-form", inputs: ["formArray"] }] }); }
2597
2594
  }
2598
2595
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.1", ngImport: i0, type: DCAgentCardFormComponent, decorators: [{
2599
2596
  type: Component,
@@ -2618,7 +2615,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.1", ngImpor
2618
2615
  PopoverModule,
2619
2616
  ProviderSelectorComponent,
2620
2617
  AccountPlatformForm,
2621
- ], template: "<div class=\"top-buttons\">\n <button pButton severity=\"info\" (click)=\"checkPrompt()\" label=\"\uD83D\uDC41\uFE0F Ver instrucciones finales \uD83D\uDCD3\"></button>\n\n <button pButton severity=\"info\" (click)=\"goToDetails()\" label=\"\uD83D\uDCAC Conversar\"></button>\n <button pButton severity=\"primary\" (click)=\"saveConversation()\" label=\"\uD83D\uDCBE Guardar cambios\"></button>\n</div>\n\n<div class=\"top-buttons\">\n <p-button severity=\"help\" (click)=\"translate()\" label=\"\uD83D\uDD04 Traducir\"></p-button>\n <p-button [loading]=\"isGenerating\" severity=\"help\" (click)=\"generateCharacter()\" label=\"Generar \uD83E\uDDBE\"></p-button>\n\n <p-button severity=\"info\" (click)=\"downloadConversation()\" label=\"\uD83D\uDCC1 Exportar \u2B07\uFE0F\"></p-button>\n <p-button severity=\"info\" (click)=\"importConversation()\" label=\"\uD83C\uDCCF Importar \u2B06\uFE0F\"></p-button>\n</div>\n\n<br />\n<br />\n<form [formGroup]=\"form\" class=\"conversation-form\">\n <div class=\"form-grid\">\n <div class=\"left-column\">\n <div style=\"display: flex; gap: 15px\">\n <div class=\"form-field\">\n <label for=\"version\">Version: {{ form.controls.version.value }} <span pTooltip=\"Version number of the conversation\">\u2139\uFE0F</span></label>\n </div>\n\n <div class=\"form-field\">\n <label for=\"id\"\n >ID: <span pTooltip=\"Unique identifier for this conversation\"> {{ form.controls.id.value }} \u2139\uFE0F</span></label\n >\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"title\">Title <span pTooltip=\"T\u00EDtulo de la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <input pInputText id=\"title\" type=\"text\" formControlName=\"title\" />\n @if(form.controls.title.errors?.['required'] && form.controls.title.touched){\n <div class=\"error\"> Title is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n formControlName=\"lang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div formGroupName=\"conversationSettings\" class=\"group\">\n <h3>Conversation Settings <span pTooltip=\"Additional information about the conversation\">\u2139\uFE0F</span></h3>\n\n <div class=\"form-field\">\n <label for=\"textEngine\">\n Text Engine\n <span\n class=\"cursor-pointer\"\n (click)=\"textEngineDialog.toggle($event)\"\n pTooltip=\"Sistema de generaci\u00F3n de texto y audios. Client: el cliente llama al servidor en cada dialogo de voz/personaje, es optimo para historias, Server SSML: se sintetiza todo el audio en uno solo con los distintos cambios de voz/personaje, util para la reflexi\u00F3n porque es bilingue, utiliza dialogos en ingles y espa\u00F1ol en el mismo dialogo/audio\"\n >\u2139\uFE0F</span\n >\n </label>\n\n <p-select\n id=\"textEngine\"\n [options]=\"textEngineOptions\"\n formControlName=\"textEngine\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Text Engine'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"conversationType\">Conversation Type <span pTooltip=\"Choose the type of conversation interaction\">\u2139\uFE0F</span></label>\n <p-select\n id=\"conversationType\"\n [options]=\"conversationOptions\"\n formControlName=\"conversationType\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Conversation Type'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label> Auto Start <span pTooltip=\"Start conversation automatically\">\u2139\uFE0F</span> </label>\n <p-toggleSwitch formControlName=\"autoStart\"> </p-toggleSwitch>\n </div>\n </div>\n\n <div formGroupName=\"tts\" class=\"group\">\n <h3>TTS Settings <span pTooltip=\"Text-to-Speech configuration options\">\u2139\uFE0F</span></h3>\n\n <div class=\"form-field\">\n <label for=\"voice\">Voice <span pTooltip=\"Select the primary voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-select\n id=\"voice\"\n [options]=\"voiceTTSOptions\"\n formControlName=\"voice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Voice'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"secondaryVoice\">Secondary Voice <span pTooltip=\"Select an alternative voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-select\n id=\"secondaryVoice\"\n [options]=\"voiceTTSOptions\"\n formControlName=\"secondaryVoice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Secondary Voice'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"speed\">Speed <span pTooltip=\"Set the speech rate for text-to-speech conversion\">\u2139\uFE0F</span></label>\n <input pInputText id=\"speed\" type=\"text\" formControlName=\"speed\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"speedRate\">Speed Rate <span pTooltip=\"Adjust the rate of speech delivery\">\u2139\uFE0F</span></label>\n <input pInputText id=\"speedRate\" type=\"number\" formControlName=\"speedRate\" step=\"0.1\" />\n </div>\n </div>\n\n <div formGroupName=\"metaApp\" class=\"group\">\n <h3>Meta Information <span pTooltip=\"Additional information about the conversation\">\u2139\uFE0F</span></h3>\n <div class=\"form-field\">\n <label for=\"authorId\">Author ID <span pTooltip=\"Unique identifier for the conversation author\">\u2139\uFE0F</span></label>\n <input pInputText id=\"authorId\" type=\"text\" formControlName=\"authorId\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"authorEmail\">Author Email \u2139\uFE0F</label>\n <input pInputText id=\"authorEmail\" type=\"email\" formControlName=\"authorEmail\" />\n <div class=\"error\" *ngIf=\"form.get('metaApp.authorEmail')?.errors?.['email'] && form.get('metaApp.authorEmail')?.touched\">\n Please enter a valid email address\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"takenCount\"\n >Taken Count <span pTooltip=\"Es el contador de cuantas veces se ha tomado esta conversaci\u00F3n, no sirve por ahora\"> \u2139\uFE0F</span></label\n >\n <input pInputText id=\"takenCount\" type=\"number\" formControlName=\"takenCount\" />\n </div>\n\n <div class=\"form-field checkbox\">\n <label>\n <p-checkbox [binary]=\"true\" formControlName=\"isPublic\" />\n Public\n </label>\n </div>\n\n <div class=\"form-field checkbox\">\n <label>\n <p-checkbox [binary]=\"true\" formControlName=\"isPublished\" />\n Published\n </label>\n </div>\n </div>\n\n <div class=\"group\">\n <h4>Model Settings <span pTooltip=\"AI model configuration\">\u2139\uFE0F</span></h4>\n\n <dc-provider-selector [parentForm]=\"form.controls.model\"></dc-provider-selector>\n </div>\n\n <div class=\"group\">\n <h4>Gestion de cuentas</h4>\n <account-platform-form [formArray]=\"form.controls.accounts\"></account-platform-form>\n </div>\n </div>\n\n <div class=\"right-column\">\n <div style=\"position: relative; min-height: 60px\">\n @if (conversation?.assets?.bannerImg?.url) {\n <img [src]=\"conversation.assets.bannerImg.url\" class=\"main-banner-image-card\" />\n } @if(agentCardId) {\n\n <dc-cropper-modal\n style=\"position: absolute; bottom: 10px; right: 10px\"\n #cropperBanner\n id=\"cropperBanner\"\n [buttonLabel]=\"conversation?.assets?.bannerImg?.url ? 'Cambiar el banner' : 'Cargar un banner'\"\n [imgStorageSettings]=\"bannerImgSettings\"\n [currentStorage]=\"conversation?.assets?.bannerImg\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'bannerImg')\"></dc-cropper-modal>\n\n }\n </div>\n <div style=\"position: relative\">\n @if (conversation?.assets?.image?.url) {\n\n <img [src]=\"conversation.assets.image.url\" class=\"main-image-card\" />\n } @if (!agentCardId) {\n <button pButton (click)=\"saveConversation()\"> Guarda el scenario para subir la imagen</button>\n } @else {\n\n <dc-cropper-modal\n style=\"position: absolute; bottom: 10px; left: 50%\"\n id=\"cropperCardImage\"\n #cropperCardImage\n [buttonLabel]=\"conversation?.assets?.image?.url ? 'Cambiar imagen' : 'Cargar una imagen'\"\n [imgStorageSettings]=\"imageStorageSettings\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'image')\"></dc-cropper-modal>\n }\n </div>\n\n <div>\n <h4>Agregar stickers</h4>\n\n <dc-cropper-modal\n id=\"cropperCardImage\"\n #cropperStickers\n [buttonLabel]=\"'agregar sticker'\"\n [imgStorageSettings]=\"stickerStorageSettings\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'sticker')\"></dc-cropper-modal>\n </div>\n\n <div style=\"display: flex; flex-wrap: wrap; gap: 10px\">\n @for (sticker of conversation?.assets?.stickers; track sticker.url) {\n <div style=\"position: relative\">\n <img width=\"100\" [src]=\"sticker.url\" alt=\"\" />\n <p-button (click)=\"removeSticker(sticker)\" class=\"remove-sticker\" icon=\"pi pi-times\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\" />\n </div>\n }\n </div>\n\n <!-- <input pInputText type=\"file\" accept=\"image/*\" (change)=\"onImageSelected($event)\" /> -->\n\n <div formGroupName=\"characterCard\">\n <div formGroupName=\"data\" class=\"card-group\">\n <h3>Character Card <span pTooltip=\"Informaci\u00F3n de la ficha del personaje\">\u2139\uFE0F</span></h3>\n <div class=\"form-field\">\n <label for=\"cardName\">Name <span pTooltip=\"El nombre del personaje\">\u2139\uFE0F</span></label>\n <input pInputText id=\"cardName\" type=\"text\" formControlName=\"name\" />\n <div class=\"error\" *ngIf=\"form.get('characterCard.data.name')?.errors?.['required'] && form.get('characterCard.data.name')?.touched\">\n Name is required\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardDescription\">Description <span pTooltip=\"Descripci\u00F3n detallada del personaje\">\u2139\uFE0F</span></label>\n <textarea class=\"textmin\" rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardDescription\" formControlName=\"description\"></textarea>\n <div class=\"error\" *ngIf=\"form.get('characterCard.data.description')?.errors?.['required'] && form.get('characterCard.data.description')?.touched\">\n Description is required\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardScenario\">Scenario <span pTooltip=\"Describe the context or setting for the conversation\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardScenario\" formControlName=\"scenario\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardFirstMessage\">\n First Message\n <span pTooltip=\"Es muy importante que la historia inicie bien, ya que es el patr\u00F3n inicial para la AI, respetar las convenciones de texto\"\n >\u2139\uFE0F</span\n >\n\n <p-togglebutton\n [formControl]=\"markdownForm.controls.seeMarkdown\"\n [onLabel]=\"'Editar'\"\n [offLabel]=\"'Ver Markdown Texto'\"\n size=\"small\"\n styleClass=\"min-w-16\"\n (onChange)=\"checkCdr()\" />\n </label>\n\n @if(markdownForm.controls.seeMarkdown.value){\n <div [innerHTML]=\"form.controls.characterCard.controls.data.controls.first_mes.value | mdToHtmlArray\"></div>\n }@else{\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardFirstMessage\" formControlName=\"first_mes\"> </textarea>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"mes_example\">Mensajes de Ejemplo <span pTooltip=\"Importante para el estilo de la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"mes_example\" formControlName=\"mes_example\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardCreatorNotes\">Creator Notes <span pTooltip=\"son solo notas del creador, no afecta nada a la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardCreatorNotes\" formControlName=\"creator_notes\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardSystemPrompt\">System Prompt (Opcional) <span pTooltip=\"Instrucciones del sistema para la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardSystemPrompt\" formControlName=\"system_prompt\"></textarea>\n <div\n class=\"error\"\n *ngIf=\"form.get('characterCard.data.system_prompt')?.errors?.['required'] && form.get('characterCard.data.system_prompt')?.touched\">\n System prompt is required\n </div>\n </div>\n\n <div style=\"display: flex; flex-direction: column\">\n <label for=\"cardPostHistoryInstructions\"\n >Post-History Instructions (Opcional)\n <span\n pTooltip=\"Dejar en blanco, al menos que se sepa como funciona, esto se llama jailbreak, es para darle instrucciones finales y m\u00E1s importantes al modelo\"\n >\u2139\uFE0F</span\n ></label\n >\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" formControlName=\"post_history_instructions\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardAlternateGreetings\">Alternate Greetings <span pTooltip=\"Saludos alternativos para comenzar una historia diferente\">\u2139\uFE0F</span></label>\n <div class=\"array-field\">\n <div\n *ngFor=\"let greeting of form.controls.characterCard.controls.data.controls.alternate_greetings.controls; let i = index\"\n class=\"array-item\"\n style=\"position: relative\">\n <textarea\n pTextarea\n rows=\"1\"\n [autoResize]=\"true\"\n [id]=\"'cardAlternateGreeting' + i\"\n [formControl]=\"greeting\"\n (input)=\"updateArrayField('alternate_greetings', i, $event)\">\n </textarea>\n <button pButton severity=\"danger\" class=\"remove-button\" (click)=\"removeArrayItem('alternate_greetings', i)\">&#x2716;</button>\n </div>\n <button pButton severity=\"info\" (click)=\"addArrayItem('alternate_greetings')\">Add Greeting</button>\n </div>\n </div>\n\n <div class=\"form-field\">\n <label pTooltip=\"Agrega las categorias\" for=\"cardTags\">Tags \u2139\uFE0F</label>\n <div class=\"array-field\">\n <div *ngFor=\"let tag of form.controls.characterCard.controls.data.controls.tags.controls; let i = index\" class=\"array-item\">\n <input [id]=\"'cardTag' + i\" type=\"text\" [formControl]=\"tag\" (input)=\"updateArrayField('tags', i, $event)\" />\n <button pButton severity=\"danger\" (click)=\"removeArrayItem('tags', i)\">Remove</button>\n </div>\n <button pButton severity=\"info\" (click)=\"addArrayItem('tags')\">Add Tag</button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</form>\n\n<p-popover #textEngineDialog header=\"Text Engine Information\">\n <div class=\"p-4\">\n <h3>Text Engine Types</h3>\n <ul>\n <li> <strong>Texto Simple</strong> La conversaci\u00F3n es como chatgpt, preguntas y responde, es la m\u00E1s b\u00E1sica</li>\n\n <li\n ><strong>Multi Mensajes</strong> Utiliza markdown (recomendable entenderlo), sirve para darle formato al texto y sea m\u00E1s agradable de leer, el sistema\n puede partir dialogos que tienen distinto formato, como normal, cursiva y negritas, asi puede generar distintas voces y estilo para el narrador y\n personaje principal</li\n >\n <li\n ><strong>MD SSML :</strong> Markdown con Lenguaje de marcaci\u00F3n de s\u00EDntesis de voz (SSML), es tambien markdown pero a diferencia de multimessage, solo se\n presenta un mensaje. y la voz se genera para toda la linea,normalmente lo uso para conversaciones bilingues.</li\n >\n </ul>\n </div>\n</p-popover>\n\n<div class=\"float-button\">\n <p-button icon=\"pi pi-save\" (click)=\"saveConversation()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n</div>\n", styles: [".textmin{min-width:36vw}.main-image-card{max-width:280px;display:block;margin:0 auto;border-radius:8px}.main-banner-image-card{border-radius:8px}.remove-sticker{position:absolute;top:5px;right:5px}.conversation-form{max-width:100%;padding:20px;background-color:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a}.conversation-form .card-group{background-color:#f8f9fa;padding:20px;border-radius:6px;margin-bottom:24px}.conversation-form .card-group h3{margin:0 0 20px;color:#2c3e50;font-size:1.25rem}.conversation-form .form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:2rem;width:100%;max-width:100%}@media (max-width: 768px){.conversation-form .form-grid{grid-template-columns:1fr}}.conversation-form .form-field{margin-bottom:1.5rem;display:flex;flex-direction:column;gap:.5rem}.conversation-form .form-field label{font-weight:500}.conversation-form .form-field textarea{resize:vertical}.conversation-form .form-field.checkbox{flex-direction:row;align-items:center;gap:.5rem}.conversation-form .form-field.checkbox input[type=checkbox]{width:auto}.conversation-form .form-field .error{color:#dc3545;font-size:.875rem;margin-top:.25rem}.conversation-form .form-field .remove-button{position:absolute;border:none;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;cursor:pointer;top:-10px;right:-10px}.conversation-form .left-column,.conversation-form .right-column{display:flex;flex-direction:column;gap:1rem}.conversation-form .array-field{display:flex;flex-direction:column;gap:.5rem}.conversation-form .array-field .array-item{display:flex;gap:.5rem}.conversation-form .array-field .array-item input,.conversation-form .array-field .array-item textarea{flex:1}.conversation-form .array-field .array-item button{padding:.5rem}.conversation-form .array-field button[type=button]{background-color:#28a745;color:#fff;border:none;padding:8px 12px;border-radius:4px;cursor:pointer;transition:background-color .2s}.conversation-form .array-field button[type=button]:hover{background-color:#218838}.conversation-form .group,.conversation-form .meta-group,.conversation-form .card-group{background-color:#f8f9fa;padding:1rem;border-radius:4px;margin-bottom:1.5rem}.conversation-form .group h3,.conversation-form .meta-group h3,.conversation-form .card-group h3{margin-top:0;margin-bottom:1rem}.top-buttons{display:flex;justify-content:space-between;margin-bottom:2rem;gap:1rem}.top-buttons button{flex:1}::ng-deep em{font-weight:900;color:#014a93}.float-button{position:fixed;bottom:4rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}\n"] }]
2618
+ ], template: "<div class=\"top-buttons\">\n <button pButton severity=\"info\" (click)=\"checkPrompt()\" label=\"\uD83D\uDC41\uFE0F Ver instrucciones finales \uD83D\uDCD3\"></button>\n\n <button pButton severity=\"info\" (click)=\"goToDetails()\" label=\"\uD83D\uDCAC Conversar\"></button>\n <button pButton severity=\"primary\" (click)=\"saveConversation()\" label=\"\uD83D\uDCBE Guardar cambios\"></button>\n</div>\n\n<div class=\"top-buttons\">\n <p-button severity=\"help\" (click)=\"translate()\" label=\"\uD83D\uDD04 Traducir\"></p-button>\n <p-button [loading]=\"isGenerating\" severity=\"help\" (click)=\"generateCharacter()\" label=\"Generar \uD83E\uDDBE\"></p-button>\n\n <p-button severity=\"info\" (click)=\"downloadConversation()\" label=\"\uD83D\uDCC1 Exportar \u2B07\uFE0F\"></p-button>\n <p-button severity=\"info\" (click)=\"importConversation()\" label=\"\uD83C\uDCCF Importar \u2B06\uFE0F\"></p-button>\n</div>\n\n<br />\n<br />\n<form [formGroup]=\"form\" class=\"conversation-form\">\n <div class=\"form-grid\">\n <div class=\"left-column\">\n <div style=\"display: flex; gap: 15px\">\n <div class=\"form-field\">\n <label for=\"version\">Version: {{ form.controls.version.value }} <span pTooltip=\"Version number of the conversation\">\u2139\uFE0F</span></label>\n </div>\n\n <div class=\"form-field\">\n <label for=\"id\"\n >ID: <span pTooltip=\"Unique identifier for this conversation\"> {{ form.controls.id.value }} \u2139\uFE0F</span></label\n >\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"title\">Title <span pTooltip=\"T\u00EDtulo de la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <input pInputText id=\"title\" type=\"text\" formControlName=\"title\" />\n @if(form.controls.title.errors?.['required'] && form.controls.title.touched){\n <div class=\"error\"> Title is required </div>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"lang\">Language <span pTooltip=\"Select the primary language for the conversation\">\u2139\uFE0F</span></label>\n <p-select\n id=\"lang\"\n [options]=\"languageOptions\"\n formControlName=\"lang\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Language'\"></p-select>\n </div>\n\n <div formGroupName=\"conversationSettings\" class=\"group\">\n <h3>Conversation Settings <span pTooltip=\"Additional information about the conversation\">\u2139\uFE0F</span></h3>\n\n <div class=\"form-field\">\n <label for=\"textEngine\">\n Text Engine\n <span\n class=\"cursor-pointer\"\n (click)=\"textEngineDialog.toggle($event)\"\n pTooltip=\"Sistema de generaci\u00F3n de texto y audios. Client: el cliente llama al servidor en cada dialogo de voz/personaje, es optimo para historias, Server SSML: se sintetiza todo el audio en uno solo con los distintos cambios de voz/personaje, util para la reflexi\u00F3n porque es bilingue, utiliza dialogos en ingles y espa\u00F1ol en el mismo dialogo/audio\"\n >\u2139\uFE0F</span\n >\n </label>\n\n <p-select\n id=\"textEngine\"\n [options]=\"textEngineOptions\"\n formControlName=\"textEngine\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Text Engine'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"conversationType\">Conversation Type <span pTooltip=\"Choose the type of conversation interaction\">\u2139\uFE0F</span></label>\n <p-select\n id=\"conversationType\"\n [options]=\"conversationOptions\"\n formControlName=\"conversationType\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'Select Conversation Type'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label> Auto Start <span pTooltip=\"Start conversation automatically\">\u2139\uFE0F</span> </label>\n <p-toggleSwitch formControlName=\"autoStart\"> </p-toggleSwitch>\n </div>\n </div>\n\n <div formGroupName=\"tts\" class=\"group\">\n <h3>TTS Settings <span pTooltip=\"Text-to-Speech configuration options\">\u2139\uFE0F</span></h3>\n\n <div class=\"form-field\">\n <label for=\"voice\">Voice <span pTooltip=\"Select the primary voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-select\n id=\"voice\"\n [options]=\"voiceTTSOptions\"\n formControlName=\"voice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Voice'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"secondaryVoice\">Secondary Voice <span pTooltip=\"Select an alternative voice for text-to-speech\">\u2139\uFE0F</span></label>\n <p-select\n id=\"secondaryVoice\"\n [options]=\"voiceTTSOptions\"\n formControlName=\"secondaryVoice\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [placeholder]=\"'Select Secondary Voice'\"></p-select>\n </div>\n\n <div class=\"form-field\">\n <label for=\"speed\">Speed <span pTooltip=\"Set the speech rate for text-to-speech conversion\">\u2139\uFE0F</span></label>\n <input pInputText id=\"speed\" type=\"text\" formControlName=\"speed\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"speedRate\">Speed Rate <span pTooltip=\"Adjust the rate of speech delivery\">\u2139\uFE0F</span></label>\n <input pInputText id=\"speedRate\" type=\"number\" formControlName=\"speedRate\" step=\"0.1\" />\n </div>\n </div>\n\n <div formGroupName=\"metaApp\" class=\"group\">\n <h3>Meta Information <span pTooltip=\"Additional information about the conversation\">\u2139\uFE0F</span></h3>\n <div class=\"form-field\">\n <label for=\"authorId\">Author ID <span pTooltip=\"Unique identifier for the conversation author\">\u2139\uFE0F</span></label>\n <input pInputText id=\"authorId\" type=\"text\" formControlName=\"authorId\" />\n </div>\n\n <div class=\"form-field\">\n <label for=\"authorEmail\">Author Email \u2139\uFE0F</label>\n <input pInputText id=\"authorEmail\" type=\"email\" formControlName=\"authorEmail\" />\n <div class=\"error\" *ngIf=\"form.get('metaApp.authorEmail')?.errors?.['email'] && form.get('metaApp.authorEmail')?.touched\">\n Please enter a valid email address\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"takenCount\"\n >Taken Count <span pTooltip=\"Es el contador de cuantas veces se ha tomado esta conversaci\u00F3n, no sirve por ahora\"> \u2139\uFE0F</span></label\n >\n <input pInputText id=\"takenCount\" type=\"number\" formControlName=\"takenCount\" />\n </div>\n\n <div class=\"form-field checkbox\">\n <label>\n <p-checkbox [binary]=\"true\" formControlName=\"isPublic\" />\n Public\n </label>\n </div>\n\n <div class=\"form-field checkbox\">\n <label>\n <p-checkbox [binary]=\"true\" formControlName=\"isPublished\" />\n Published\n </label>\n </div>\n </div>\n\n <div class=\"group\">\n <h4>Model Settings <span pTooltip=\"AI model configuration\">\u2139\uFE0F</span></h4>\n\n <dc-provider-selector [parentForm]=\"form.controls.model\"></dc-provider-selector>\n </div>\n\n <div class=\"group\">\n <h4>Gestion de cuentas</h4>\n @if(form.controls.accounts){\n <account-platform-form [formArray]=\"form.controls.accounts\"></account-platform-form>\n\n }\n </div>\n </div>\n\n <div class=\"right-column\">\n <div style=\"position: relative; min-height: 60px\">\n @if (conversation?.assets?.bannerImg?.url) {\n <img [src]=\"conversation.assets.bannerImg.url\" class=\"main-banner-image-card\" />\n } @if(agentCardId) {\n\n <dc-cropper-modal\n style=\"position: absolute; bottom: 10px; right: 10px\"\n #cropperBanner\n id=\"cropperBanner\"\n [buttonLabel]=\"conversation?.assets?.bannerImg?.url ? 'Cambiar el banner' : 'Cargar un banner'\"\n [imgStorageSettings]=\"bannerImgSettings\"\n [currentStorage]=\"conversation?.assets?.bannerImg\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'bannerImg')\"></dc-cropper-modal>\n\n }\n </div>\n <div style=\"position: relative\">\n @if (conversation?.assets?.image?.url) {\n\n <img [src]=\"conversation.assets.image.url\" class=\"main-image-card\" />\n } @if (!agentCardId) {\n <button pButton (click)=\"saveConversation()\"> Guarda el scenario para subir la imagen</button>\n } @else {\n\n <dc-cropper-modal\n style=\"position: absolute; bottom: 10px; left: 50%\"\n id=\"cropperCardImage\"\n #cropperCardImage\n [buttonLabel]=\"conversation?.assets?.image?.url ? 'Cambiar imagen' : 'Cargar una imagen'\"\n [imgStorageSettings]=\"imageStorageSettings\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'image')\"></dc-cropper-modal>\n }\n </div>\n\n <div>\n <h4>Agregar stickers</h4>\n\n <dc-cropper-modal\n id=\"cropperCardImage\"\n #cropperStickers\n [buttonLabel]=\"'agregar sticker'\"\n [imgStorageSettings]=\"stickerStorageSettings\"\n (onFileSelected)=\"onImageSelected($event)\"\n (imageUploaded)=\"onImageUploaded($event, 'sticker')\"></dc-cropper-modal>\n </div>\n\n <div style=\"display: flex; flex-wrap: wrap; gap: 10px\">\n @for (sticker of conversation?.assets?.stickers; track sticker.url) {\n <div style=\"position: relative\">\n <img width=\"100\" [src]=\"sticker.url\" alt=\"\" />\n <p-button (click)=\"removeSticker(sticker)\" class=\"remove-sticker\" icon=\"pi pi-times\" [rounded]=\"true\" [text]=\"true\" severity=\"danger\" />\n </div>\n }\n </div>\n\n <!-- <input pInputText type=\"file\" accept=\"image/*\" (change)=\"onImageSelected($event)\" /> -->\n\n <div formGroupName=\"characterCard\">\n <div formGroupName=\"data\" class=\"card-group\">\n <h3>Character Card <span pTooltip=\"Informaci\u00F3n de la ficha del personaje\">\u2139\uFE0F</span></h3>\n <div class=\"form-field\">\n <label for=\"cardName\">Name <span pTooltip=\"El nombre del personaje\">\u2139\uFE0F</span></label>\n <input pInputText id=\"cardName\" type=\"text\" formControlName=\"name\" />\n <div class=\"error\" *ngIf=\"form.get('characterCard.data.name')?.errors?.['required'] && form.get('characterCard.data.name')?.touched\">\n Name is required\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardDescription\">Description <span pTooltip=\"Descripci\u00F3n detallada del personaje\">\u2139\uFE0F</span></label>\n <textarea class=\"textmin\" rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardDescription\" formControlName=\"description\"></textarea>\n <div class=\"error\" *ngIf=\"form.get('characterCard.data.description')?.errors?.['required'] && form.get('characterCard.data.description')?.touched\">\n Description is required\n </div>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardScenario\">Scenario <span pTooltip=\"Describe the context or setting for the conversation\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardScenario\" formControlName=\"scenario\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardFirstMessage\">\n First Message\n <span pTooltip=\"Es muy importante que la historia inicie bien, ya que es el patr\u00F3n inicial para la AI, respetar las convenciones de texto\"\n >\u2139\uFE0F</span\n >\n\n <p-togglebutton\n [formControl]=\"markdownForm.controls.seeMarkdown\"\n [onLabel]=\"'Editar'\"\n [offLabel]=\"'Ver Markdown Texto'\"\n size=\"small\"\n styleClass=\"min-w-16\"\n (onChange)=\"checkCdr()\" />\n </label>\n\n @if(markdownForm.controls.seeMarkdown.value){\n <div [innerHTML]=\"form.controls.characterCard.controls.data.controls.first_mes.value | mdToHtmlArray\"></div>\n }@else{\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardFirstMessage\" formControlName=\"first_mes\"> </textarea>\n }\n </div>\n\n <div class=\"form-field\">\n <label for=\"mes_example\">Mensajes de Ejemplo <span pTooltip=\"Importante para el estilo de la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"mes_example\" formControlName=\"mes_example\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardCreatorNotes\">Creator Notes <span pTooltip=\"son solo notas del creador, no afecta nada a la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardCreatorNotes\" formControlName=\"creator_notes\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardSystemPrompt\">System Prompt (Opcional) <span pTooltip=\"Instrucciones del sistema para la conversaci\u00F3n\">\u2139\uFE0F</span></label>\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" id=\"cardSystemPrompt\" formControlName=\"system_prompt\"></textarea>\n <div\n class=\"error\"\n *ngIf=\"form.get('characterCard.data.system_prompt')?.errors?.['required'] && form.get('characterCard.data.system_prompt')?.touched\">\n System prompt is required\n </div>\n </div>\n\n <div style=\"display: flex; flex-direction: column\">\n <label for=\"cardPostHistoryInstructions\"\n >Post-History Instructions (Opcional)\n <span\n pTooltip=\"Dejar en blanco, al menos que se sepa como funciona, esto se llama jailbreak, es para darle instrucciones finales y m\u00E1s importantes al modelo\"\n >\u2139\uFE0F</span\n ></label\n >\n <textarea rows=\"1\" pTextarea [autoResize]=\"true\" formControlName=\"post_history_instructions\"></textarea>\n </div>\n\n <div class=\"form-field\">\n <label for=\"cardAlternateGreetings\">Alternate Greetings <span pTooltip=\"Saludos alternativos para comenzar una historia diferente\">\u2139\uFE0F</span></label>\n <div class=\"array-field\">\n <div\n *ngFor=\"let greeting of form.controls.characterCard.controls.data.controls.alternate_greetings.controls; let i = index\"\n class=\"array-item\"\n style=\"position: relative\">\n <textarea\n pTextarea\n rows=\"1\"\n [autoResize]=\"true\"\n [id]=\"'cardAlternateGreeting' + i\"\n [formControl]=\"greeting\"\n (input)=\"updateArrayField('alternate_greetings', i, $event)\">\n </textarea>\n <button pButton severity=\"danger\" class=\"remove-button\" (click)=\"removeArrayItem('alternate_greetings', i)\">&#x2716;</button>\n </div>\n <button pButton severity=\"info\" (click)=\"addArrayItem('alternate_greetings')\">Add Greeting</button>\n </div>\n </div>\n\n <div class=\"form-field\">\n <label pTooltip=\"Agrega las categorias\" for=\"cardTags\">Tags \u2139\uFE0F</label>\n <div class=\"array-field\">\n <div *ngFor=\"let tag of form.controls.characterCard.controls.data.controls.tags.controls; let i = index\" class=\"array-item\">\n <input [id]=\"'cardTag' + i\" type=\"text\" [formControl]=\"tag\" (input)=\"updateArrayField('tags', i, $event)\" />\n <button pButton severity=\"danger\" (click)=\"removeArrayItem('tags', i)\">Remove</button>\n </div>\n <button pButton severity=\"info\" (click)=\"addArrayItem('tags')\">Add Tag</button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</form>\n\n<p-popover #textEngineDialog header=\"Text Engine Information\">\n <div class=\"p-4\">\n <h3>Text Engine Types</h3>\n <ul>\n <li> <strong>Texto Simple</strong> La conversaci\u00F3n es como chatgpt, preguntas y responde, es la m\u00E1s b\u00E1sica</li>\n\n <li\n ><strong>Multi Mensajes</strong> Utiliza markdown (recomendable entenderlo), sirve para darle formato al texto y sea m\u00E1s agradable de leer, el sistema\n puede partir dialogos que tienen distinto formato, como normal, cursiva y negritas, asi puede generar distintas voces y estilo para el narrador y\n personaje principal</li\n >\n <li\n ><strong>MD SSML :</strong> Markdown con Lenguaje de marcaci\u00F3n de s\u00EDntesis de voz (SSML), es tambien markdown pero a diferencia de multimessage, solo se\n presenta un mensaje. y la voz se genera para toda la linea,normalmente lo uso para conversaciones bilingues.</li\n >\n </ul>\n </div>\n</p-popover>\n\n<div class=\"float-button\">\n <p-button icon=\"pi pi-save\" (click)=\"saveConversation()\" severity=\"primary\" [rounded]=\"true\" [raised]=\"true\" pTooltip=\"Guardar (Ctrl + S)\"> </p-button>\n</div>\n", styles: [".textmin{min-width:36vw}.main-image-card{max-width:280px;display:block;margin:0 auto;border-radius:8px}.main-banner-image-card{border-radius:8px}.remove-sticker{position:absolute;top:5px;right:5px}.conversation-form{max-width:100%;padding:20px;background-color:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a}.conversation-form .card-group{background-color:#f8f9fa;padding:20px;border-radius:6px;margin-bottom:24px}.conversation-form .card-group h3{margin:0 0 20px;color:#2c3e50;font-size:1.25rem}.conversation-form .form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:2rem;width:100%;max-width:100%}@media (max-width: 768px){.conversation-form .form-grid{grid-template-columns:1fr}}.conversation-form .form-field{margin-bottom:1.5rem;display:flex;flex-direction:column;gap:.5rem}.conversation-form .form-field label{font-weight:500}.conversation-form .form-field textarea{resize:vertical}.conversation-form .form-field.checkbox{flex-direction:row;align-items:center;gap:.5rem}.conversation-form .form-field.checkbox input[type=checkbox]{width:auto}.conversation-form .form-field .error{color:#dc3545;font-size:.875rem;margin-top:.25rem}.conversation-form .form-field .remove-button{position:absolute;border:none;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;cursor:pointer;top:-10px;right:-10px}.conversation-form .left-column,.conversation-form .right-column{display:flex;flex-direction:column;gap:1rem}.conversation-form .array-field{display:flex;flex-direction:column;gap:.5rem}.conversation-form .array-field .array-item{display:flex;gap:.5rem}.conversation-form .array-field .array-item input,.conversation-form .array-field .array-item textarea{flex:1}.conversation-form .array-field .array-item button{padding:.5rem}.conversation-form .array-field button[type=button]{background-color:#28a745;color:#fff;border:none;padding:8px 12px;border-radius:4px;cursor:pointer;transition:background-color .2s}.conversation-form .array-field button[type=button]:hover{background-color:#218838}.conversation-form .group,.conversation-form .meta-group,.conversation-form .card-group{background-color:#f8f9fa;padding:1rem;border-radius:4px;margin-bottom:1.5rem}.conversation-form .group h3,.conversation-form .meta-group h3,.conversation-form .card-group h3{margin-top:0;margin-bottom:1rem}.top-buttons{display:flex;justify-content:space-between;margin-bottom:2rem;gap:1rem}.top-buttons button{flex:1}::ng-deep em{font-weight:900;color:#014a93}.float-button{position:fixed;bottom:4rem;right:2rem;z-index:1000;display:flex;gap:1px}.float-button :host ::ng-deep .p-button{width:4rem;height:4rem;border-radius:50%}\n"] }]
2622
2619
  }], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: i2$2.MultiImagesStorageService }, { type: AgentCardsAbstractService, decorators: [{
2623
2620
  type: Inject,
2624
2621
  args: [CONVERSATION_AI_TOKEN]
@@ -2682,16 +2679,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.1", ngImpor
2682
2679
  // This component contains a really avanced strategy to dinamically render Conversation Cards Details so every app can implement it with their own Style and Behavior
2683
2680
  // The trick is use NGFOR with ngComponentOutlet and pass input, problem is, is not possible to get Outpus events, Option one is use injector with ngComponentOutlet and pass context function to handle , but somehow it inject html and due to sanity im not able to see popups
2684
2681
  // So solution is handle subcription in this component manually. if i have access to all references, i can do everything manually.
2685
- class ConversationCardListsComponent extends PaginationBase {
2682
+ class AgentCardListComponent extends PaginationBase {
2686
2683
  constructor(agentCardService, toastService, route, router, cdr) {
2687
2684
  super(route, router);
2688
2685
  this.agentCardService = agentCardService;
2689
2686
  this.toastService = toastService;
2690
2687
  this.cdr = cdr;
2688
+ this.viewMode = 'cards';
2691
2689
  this.gridLayout = true;
2692
2690
  this.goToDetailsEvent = new EventEmitter();
2693
2691
  this.goToEditEvent = new EventEmitter();
2694
2692
  this.deleteEvent = new EventEmitter();
2693
+ this.onSelect = new EventEmitter();
2694
+ this.columns = [
2695
+ { field: 'assets.image.url', header: 'Image', type: 'image' },
2696
+ { field: 'characterCard.data.name', header: 'Character Name', type: 'text' },
2697
+ { field: 'title', header: 'Title', type: 'text' },
2698
+ ];
2695
2699
  this.conversationCards = [];
2696
2700
  this.cardEventSubs = [];
2697
2701
  this.cardComponent = null;
@@ -2792,19 +2796,35 @@ class ConversationCardListsComponent extends PaginationBase {
2792
2796
  this.cdr.detectChanges();
2793
2797
  this.subscribeDinamicInstantToEvents();
2794
2798
  }
2795
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.1", ngImport: i0, type: ConversationCardListsComponent, deps: [{ token: CONVERSATION_AI_TOKEN }, { token: TOAST_ALERTS_TOKEN }, { token: i1$3.ActivatedRoute }, { token: i1$3.Router }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
2796
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.1", type: ConversationCardListsComponent, isStandalone: true, selector: "dc-agent-card-lists", inputs: { customCardComponent: "customCardComponent", gridLayout: "gridLayout", getCustomButtons: "getCustomButtons" }, outputs: { goToDetailsEvent: "goToDetailsEvent", goToEditEvent: "goToEditEvent", deleteEvent: "deleteEvent" }, viewQueries: [{ propertyName: "outlets", predicate: ["outlet"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<dc-filter-bar [isAdmin]=\"true\" (onNew)=\"goToEdit()\" (onSearch)=\"search($event)\" (onFilterChange)=\"filterChange($event)\"></dc-filter-bar>\n\n<div class=\"conversation-card-lists\">\n @if(!isLoading) {\n\n <div [ngClass]=\"{ 'cards-container': gridLayout }\">\n @for (card of conversationCards; track card) {\n <div style=\"position: relative\">\n <ng-container #outlet=\"ngComponentOutlet\" [ngComponentOutlet]=\"cardComponent\" [ngComponentOutletInputs]=\"{ card: card }\"> </ng-container>\n\n @if(getCustomButtons) {\n\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(card)\"\n [radius]=\"60\"\n type=\"semi-circle\"\n direction=\"left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\" />\n </div>\n\n }\n </div>\n }\n </div>\n }\n</div>\n\n@if(isLoading) {\n<div>\n <p-skeleton styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"5rem\" styleClass=\"mb-2\" />\n <p-skeleton height=\"2rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" height=\"4rem\" />\n</div>\n} @if(conversationCards.length === 0) {\n<div>\n <p>No conversations found or no connection with server</p>\n</div>\n\n}\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [".options-icon{cursor:pointer;position:absolute;top:2px;right:3px;font-size:1.2rem;color:#dde9e9;background-color:#4f486281;border-radius:50%;padding:5px;z-index:1000}.conversation-card-lists{padding:1.5rem;width:100%}.conversation-card-lists .cards-container{display:flex;flex-wrap:wrap;gap:2rem;width:100%;justify-content:center}.conversation-card-lists .cards-container>div{flex:0 0 240px}.conversation-card-lists .dc-card{position:relative;background:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a;padding:.5rem;transition:transform .2s ease,box-shadow .2s ease;display:flex;flex-direction:column;gap:2px}.conversation-card-lists .dc-card:hover{transform:translateY(-2px);box-shadow:0 4px 8px #00000026}.conversation-card-lists .dc-card .dc-card-header{position:absolute;top:10px;left:5px;border-radius:5px;padding:5px}.conversation-card-lists .dc-card .dc-card-header:before{content:\"\";position:absolute;inset:0;background-color:#4d30db81;filter:blur(2px);border-radius:5px;z-index:0}.conversation-card-lists .dc-card .dc-card-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#ece7e7;position:relative;z-index:1}.conversation-card-lists .dc-card .dc-card-content{flex:1}.conversation-card-lists .dc-card .dc-card-content p{margin:0;color:#666;line-height:1.5}.conversation-card-lists .dc-card button{padding:.5rem 1rem;border:none;border-radius:4px;background-color:#007bff;color:#fff;cursor:pointer;font-weight:500;transition:background-color .2s ease}.conversation-card-lists .dc-card button:hover{background-color:#0056b3}.conversation-card-lists .dc-card button:active{transform:translateY(1px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i3$2.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "style", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "appendTo", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first"], outputs: ["onPageChange"] }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["isAdmin", "customFilters"], outputs: ["onChangeSort", "onNew", "onSearch", "onFilterChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i6.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i5$2.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }] }); }
2799
+ selectItem(item) {
2800
+ console.log('onSelect');
2801
+ this.onSelect.emit(item);
2802
+ }
2803
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.1", ngImport: i0, type: AgentCardListComponent, deps: [{ token: CONVERSATION_AI_TOKEN }, { token: TOAST_ALERTS_TOKEN }, { token: i1$3.ActivatedRoute }, { token: i1$3.Router }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
2804
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.1", type: AgentCardListComponent, isStandalone: true, selector: "dc-agent-card-lists", inputs: { viewMode: "viewMode", customCardComponent: "customCardComponent", gridLayout: "gridLayout", getCustomButtons: "getCustomButtons" }, outputs: { goToDetailsEvent: "goToDetailsEvent", goToEditEvent: "goToEditEvent", deleteEvent: "deleteEvent", onSelect: "onSelect" }, viewQueries: [{ propertyName: "outlets", predicate: ["outlet"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if(viewMode === 'table'){\n<app-quick-table [columns]=\"columns\" [tableData]=\"conversationCards\" (onSelect)=\"selectItem($event)\"></app-quick-table>\n\n}@else{\n\n<dc-filter-bar [isAdmin]=\"true\" (onNew)=\"goToEdit()\" (onSearch)=\"search($event)\" (onFilterChange)=\"filterChange($event)\"></dc-filter-bar>\n\n<div class=\"conversation-card-lists\">\n @if(!isLoading) {\n <div [ngClass]=\"{ 'cards-container': gridLayout }\">\n @for (card of conversationCards; track card) {\n <div style=\"position: relative\">\n <ng-container #outlet=\"ngComponentOutlet\" [ngComponentOutlet]=\"cardComponent\" [ngComponentOutletInputs]=\"{ card: card }\"> </ng-container>\n\n @if(getCustomButtons) {\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(card)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\" />\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n\n@if(isLoading) {\n<div>\n <p-skeleton styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"5rem\" styleClass=\"mb-2\" />\n <p-skeleton height=\"2rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" height=\"4rem\" />\n</div>\n} @if(conversationCards.length === 0) {\n<div>\n <p>No conversations found or no connection with server</p>\n</div>\n} }\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [":host{display:block;height:100%}.options-icon{cursor:pointer;position:absolute;top:2px;right:3px;font-size:1.2rem;color:#dde9e9;background-color:#4f486281;border-radius:50%;padding:5px;z-index:1000}.conversation-card-lists{padding:1.5rem;width:100%;height:100%;display:flex;flex-direction:column}.conversation-card-lists .cards-container{display:flex;flex-wrap:wrap;gap:2rem;width:100%;justify-content:center;flex:1;overflow-y:auto;min-height:0}.conversation-card-lists .cards-container>div{flex:0 0 240px}.conversation-card-lists .dc-card{position:relative;background:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a;padding:.5rem;transition:transform .2s ease,box-shadow .2s ease;display:flex;flex-direction:column;gap:2px}.conversation-card-lists .dc-card:hover{transform:translateY(-2px);box-shadow:0 4px 8px #00000026}.conversation-card-lists .dc-card .dc-card-header{position:absolute;top:10px;left:5px;border-radius:5px;padding:5px}.conversation-card-lists .dc-card .dc-card-header:before{content:\"\";position:absolute;inset:0;background-color:#4d30db81;filter:blur(2px);border-radius:5px;z-index:0}.conversation-card-lists .dc-card .dc-card-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#ece7e7;position:relative;z-index:1}.conversation-card-lists .dc-card .dc-card-content{flex:1}.conversation-card-lists .dc-card .dc-card-content p{margin:0;color:#666;line-height:1.5}.conversation-card-lists .dc-card button{padding:.5rem 1rem;border:none;border-radius:4px;background-color:#007bff;color:#fff;cursor:pointer;font-weight:500;transition:background-color .2s ease}.conversation-card-lists .dc-card button:hover{background-color:#0056b3}.conversation-card-lists .dc-card button:active{transform:translateY(1px)}:host{display:flex;flex-direction:column;height:100%}p-paginator{margin-top:1rem;flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i3$2.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "style", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "appendTo", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first"], outputs: ["onPageChange"] }, { kind: "component", type: DCFilterBarComponent, selector: "dc-filter-bar", inputs: ["isAdmin", "customFilters"], outputs: ["onChangeSort", "onNew", "onSearch", "onFilterChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i6.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: SpeedDialModule }, { kind: "component", type: i5$2.SpeedDial, selector: "p-speeddial, p-speedDial, p-speed-dial", inputs: ["id", "model", "visible", "style", "className", "direction", "transitionDelay", "type", "radius", "mask", "disabled", "hideOnClickOutside", "buttonStyle", "buttonClassName", "maskStyle", "maskClassName", "showIcon", "hideIcon", "rotateAnimation", "ariaLabel", "ariaLabelledBy", "tooltipOptions", "buttonProps"], outputs: ["onVisibleChange", "visibleChange", "onClick", "onShow", "onHide"] }, { kind: "component", type: QuickTableComponent, selector: "app-quick-table", inputs: ["onlyView", "columns", "tableData"], outputs: ["onSelect"] }] }); }
2797
2805
  }
2798
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.1", ngImport: i0, type: ConversationCardListsComponent, decorators: [{
2806
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.1", ngImport: i0, type: AgentCardListComponent, decorators: [{
2799
2807
  type: Component,
2800
- args: [{ selector: 'dc-agent-card-lists', imports: [CommonModule, NgComponentOutlet, PopoverModule, ButtonModule, PaginatorModule, DCFilterBarComponent, SkeletonModule, SpeedDialModule], standalone: true, template: "<dc-filter-bar [isAdmin]=\"true\" (onNew)=\"goToEdit()\" (onSearch)=\"search($event)\" (onFilterChange)=\"filterChange($event)\"></dc-filter-bar>\n\n<div class=\"conversation-card-lists\">\n @if(!isLoading) {\n\n <div [ngClass]=\"{ 'cards-container': gridLayout }\">\n @for (card of conversationCards; track card) {\n <div style=\"position: relative\">\n <ng-container #outlet=\"ngComponentOutlet\" [ngComponentOutlet]=\"cardComponent\" [ngComponentOutletInputs]=\"{ card: card }\"> </ng-container>\n\n @if(getCustomButtons) {\n\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(card)\"\n [radius]=\"60\"\n type=\"semi-circle\"\n direction=\"left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\" />\n </div>\n\n }\n </div>\n }\n </div>\n }\n</div>\n\n@if(isLoading) {\n<div>\n <p-skeleton styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"5rem\" styleClass=\"mb-2\" />\n <p-skeleton height=\"2rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" height=\"4rem\" />\n</div>\n} @if(conversationCards.length === 0) {\n<div>\n <p>No conversations found or no connection with server</p>\n</div>\n\n}\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [".options-icon{cursor:pointer;position:absolute;top:2px;right:3px;font-size:1.2rem;color:#dde9e9;background-color:#4f486281;border-radius:50%;padding:5px;z-index:1000}.conversation-card-lists{padding:1.5rem;width:100%}.conversation-card-lists .cards-container{display:flex;flex-wrap:wrap;gap:2rem;width:100%;justify-content:center}.conversation-card-lists .cards-container>div{flex:0 0 240px}.conversation-card-lists .dc-card{position:relative;background:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a;padding:.5rem;transition:transform .2s ease,box-shadow .2s ease;display:flex;flex-direction:column;gap:2px}.conversation-card-lists .dc-card:hover{transform:translateY(-2px);box-shadow:0 4px 8px #00000026}.conversation-card-lists .dc-card .dc-card-header{position:absolute;top:10px;left:5px;border-radius:5px;padding:5px}.conversation-card-lists .dc-card .dc-card-header:before{content:\"\";position:absolute;inset:0;background-color:#4d30db81;filter:blur(2px);border-radius:5px;z-index:0}.conversation-card-lists .dc-card .dc-card-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#ece7e7;position:relative;z-index:1}.conversation-card-lists .dc-card .dc-card-content{flex:1}.conversation-card-lists .dc-card .dc-card-content p{margin:0;color:#666;line-height:1.5}.conversation-card-lists .dc-card button{padding:.5rem 1rem;border:none;border-radius:4px;background-color:#007bff;color:#fff;cursor:pointer;font-weight:500;transition:background-color .2s ease}.conversation-card-lists .dc-card button:hover{background-color:#0056b3}.conversation-card-lists .dc-card button:active{transform:translateY(1px)}\n"] }]
2808
+ args: [{ selector: 'dc-agent-card-lists', imports: [
2809
+ CommonModule,
2810
+ NgComponentOutlet,
2811
+ PopoverModule,
2812
+ ButtonModule,
2813
+ PaginatorModule,
2814
+ DCFilterBarComponent,
2815
+ SkeletonModule,
2816
+ SpeedDialModule,
2817
+ QuickTableComponent,
2818
+ ], standalone: true, template: "@if(viewMode === 'table'){\n<app-quick-table [columns]=\"columns\" [tableData]=\"conversationCards\" (onSelect)=\"selectItem($event)\"></app-quick-table>\n\n}@else{\n\n<dc-filter-bar [isAdmin]=\"true\" (onNew)=\"goToEdit()\" (onSearch)=\"search($event)\" (onFilterChange)=\"filterChange($event)\"></dc-filter-bar>\n\n<div class=\"conversation-card-lists\">\n @if(!isLoading) {\n <div [ngClass]=\"{ 'cards-container': gridLayout }\">\n @for (card of conversationCards; track card) {\n <div style=\"position: relative\">\n <ng-container #outlet=\"ngComponentOutlet\" [ngComponentOutlet]=\"cardComponent\" [ngComponentOutletInputs]=\"{ card: card }\"> </ng-container>\n\n @if(getCustomButtons) {\n <div style=\"position: absolute; top: 4px; right: 4px; z-index: 1000\">\n <p-speeddial\n [model]=\"getCustomButtons(card)\"\n [radius]=\"70\"\n type=\"quarter-circle\"\n direction=\"down-left\"\n [buttonProps]=\"{ severity: 'primary', rounded: true, outlined: true, raised: true }\" />\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n\n@if(isLoading) {\n<div>\n <p-skeleton styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"5rem\" styleClass=\"mb-2\" />\n <p-skeleton height=\"2rem\" styleClass=\"mb-2\" />\n <p-skeleton width=\"10rem\" height=\"4rem\" />\n</div>\n} @if(conversationCards.length === 0) {\n<div>\n <p>No conversations found or no connection with server</p>\n</div>\n} }\n\n<p-paginator\n currentPageReportTemplate=\"{{ totalRecords }} conversations\"\n [showCurrentPageReport]=\"true\"\n (onPageChange)=\"onPageChange($event)\"\n [first]=\"paginatorFirst\"\n [rows]=\"paginatorRows\"\n [totalRecords]=\"totalRecords\"\n [rowsPerPageOptions]=\"[10, 20, 30]\">\n</p-paginator>\n", styles: [":host{display:block;height:100%}.options-icon{cursor:pointer;position:absolute;top:2px;right:3px;font-size:1.2rem;color:#dde9e9;background-color:#4f486281;border-radius:50%;padding:5px;z-index:1000}.conversation-card-lists{padding:1.5rem;width:100%;height:100%;display:flex;flex-direction:column}.conversation-card-lists .cards-container{display:flex;flex-wrap:wrap;gap:2rem;width:100%;justify-content:center;flex:1;overflow-y:auto;min-height:0}.conversation-card-lists .cards-container>div{flex:0 0 240px}.conversation-card-lists .dc-card{position:relative;background:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a;padding:.5rem;transition:transform .2s ease,box-shadow .2s ease;display:flex;flex-direction:column;gap:2px}.conversation-card-lists .dc-card:hover{transform:translateY(-2px);box-shadow:0 4px 8px #00000026}.conversation-card-lists .dc-card .dc-card-header{position:absolute;top:10px;left:5px;border-radius:5px;padding:5px}.conversation-card-lists .dc-card .dc-card-header:before{content:\"\";position:absolute;inset:0;background-color:#4d30db81;filter:blur(2px);border-radius:5px;z-index:0}.conversation-card-lists .dc-card .dc-card-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#ece7e7;position:relative;z-index:1}.conversation-card-lists .dc-card .dc-card-content{flex:1}.conversation-card-lists .dc-card .dc-card-content p{margin:0;color:#666;line-height:1.5}.conversation-card-lists .dc-card button{padding:.5rem 1rem;border:none;border-radius:4px;background-color:#007bff;color:#fff;cursor:pointer;font-weight:500;transition:background-color .2s ease}.conversation-card-lists .dc-card button:hover{background-color:#0056b3}.conversation-card-lists .dc-card button:active{transform:translateY(1px)}:host{display:flex;flex-direction:column;height:100%}p-paginator{margin-top:1rem;flex-shrink:0}\n"] }]
2801
2819
  }], ctorParameters: () => [{ type: AgentCardsAbstractService, decorators: [{
2802
2820
  type: Inject,
2803
2821
  args: [CONVERSATION_AI_TOKEN]
2804
2822
  }] }, { type: i9.ToastAlertsAbstractService, decorators: [{
2805
2823
  type: Inject,
2806
2824
  args: [TOAST_ALERTS_TOKEN]
2807
- }] }, { type: i1$3.ActivatedRoute }, { type: i1$3.Router }, { type: i0.ChangeDetectorRef }], propDecorators: { customCardComponent: [{
2825
+ }] }, { type: i1$3.ActivatedRoute }, { type: i1$3.Router }, { type: i0.ChangeDetectorRef }], propDecorators: { viewMode: [{
2826
+ type: Input
2827
+ }], customCardComponent: [{
2808
2828
  type: Input
2809
2829
  }], gridLayout: [{
2810
2830
  type: Input
@@ -2816,6 +2836,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.1", ngImpor
2816
2836
  type: Output
2817
2837
  }], deleteEvent: [{
2818
2838
  type: Output
2839
+ }], onSelect: [{
2840
+ type: Output
2819
2841
  }], outlets: [{
2820
2842
  type: ViewChildren,
2821
2843
  args: ['outlet']
@@ -2868,5 +2890,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.1", ngImpor
2868
2890
  * Generated bundle index. Do not edit.
2869
2891
  */
2870
2892
 
2871
- export { AgentCardsAbstractService, AudioService, AudioSpeed, CONVERSATION_AI_TOKEN, ChatMessage, ChatMessageComponent, ChatMultiMessage, ChatRole, ChatUserSettings, ConversationCardListsComponent, ConversationDTO, ConversationMessagesDTO, ConversationType, ConversationTypeOptions, DCAgentCardFormComponent, DCChatComponent, DCConversationCardUIComponent, DCConversationPromptBuilderService, DcAgentCardDetailsComponent, EAccountsPlatform, LangCodeDescriptionEs, ProviderSelectorComponent, TextEngineOptions, TextEngines, USER_DATA_EXCHANGE, UserDataExchangeAbstractService, VoiceTTSOption, VoiceTTSOptions, WordTimestamps, characterCardStringDataDefinition, extractJsonFromResponse, provideChatAIService, provideUserDataExchange };
2893
+ export { AgentCardListComponent, AgentCardsAbstractService, AudioService, AudioSpeed, CONVERSATION_AI_TOKEN, ChatMessage, ChatMessageComponent, ChatMultiMessage, ChatRole, ChatUserSettings, ConversationDTO, ConversationMessagesDTO, ConversationType, ConversationTypeOptions, DCAgentCardFormComponent, DCChatComponent, DCConversationCardUIComponent, DCConversationPromptBuilderService, DcAgentCardDetailsComponent, EAccountsPlatform, LangCodeDescriptionEs, ProviderSelectorComponent, TextEngineOptions, TextEngines, USER_DATA_EXCHANGE, UserDataExchangeAbstractService, VoiceTTSOption, VoiceTTSOptions, WordTimestamps, characterCardStringDataDefinition, extractJsonFromResponse, provideChatAIService, provideUserDataExchange };
2872
2894
  //# sourceMappingURL=dataclouder-ngx-agent-cards.mjs.map