Skip to content

Commit

Permalink
feat: copilot chat in formula
Browse files Browse the repository at this point in the history
  • Loading branch information
meta-d committed Feb 7, 2024
1 parent 6c6c1a9 commit bd7b17d
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 81 deletions.
97 changes: 40 additions & 57 deletions apps/cloud/src/app/@shared/model/formula.component.html
Original file line number Diff line number Diff line change
@@ -1,63 +1,46 @@
<div class="flex flex-1 max-w-full" cdkDropListGroup>
<div class="ngm-theme-dark dark w-[400px] shrink-0 flex flex-col justify-start overflow-auto bg-bluegray-700 text-white p-4 group" >
<div class="w-full flex justify-start items-center my-2" cdkDrag cdkDragRootElement=".cdk-overlay-pane" cdkDragHandle>
<mat-icon displayDensity="cosy" class="-ml-2 opacity-0 group-hover:opacity-80">drag_indicator</mat-icon>
<span class="text-lg pointer-events-none">
{{ 'PAC.KEY_WORDS.CalculatedFormula' | translate: {Default: 'Calculated Formula'} }}
</span>
<span *ngIf="measure?.caption">({{measure.caption}})</span>
</div>

<div class="flex-1 flex flex-col justify-start items-stretch overflow-auto">
<ngm-search class="my-2" [formControl]="searchControl"></ngm-search>

<mat-accordion cdkDropList [cdkDropListData]="FUNCTIONS">
<mat-expansion-panel hideToggle *ngFor="let f of functions$ | async" class="mat-elevation-z" style="background: transparent">
<mat-expansion-panel-header>
<mat-panel-title cdkDrag
[cdkDragData]="f.insertText">
<span [highlight]="highlight" [caseSensitive]="false" customClasses="bg-transparent font-semibold text-amber-500"
[content]="f.label">
</span>
</mat-panel-title>
</mat-expansion-panel-header>

<ng-template matExpansionPanelContent>
<div class="my-2 text-xs font-mono italic text-slate-100">
{{f.expression}}
</div>
<markdown [textContent]="f.documentation" class="text-slate-200"></markdown>
</ng-template>
</mat-expansion-panel>
</mat-accordion>

</div>

<div class="flex">
<div ngmButtonGroup>
<button mat-raised-button color="accent" [matDialogClose]="formula">
{{ ('COMPONENTS.COMMON.Apply' | translate: {Default: 'Apply'}) }}
</button>

<button mat-button mat-dialog-close cdkFocusInitial >
{{ ('COMPONENTS.COMMON.CANCEL' | translate: {Default: 'Cancel'}) }}
</button>
</div>
<div class="ngm-theme-dark dark w-[400px] shrink-0 flex flex-col justify-start overflow-auto bg-bluegray-700 text-white p-4 group" >
<div class="w-full flex justify-start items-center my-2" cdkDrag cdkDragRootElement=".cdk-overlay-pane" cdkDragHandle>
<mat-icon displayDensity="cosy" class="-ml-2 opacity-0 group-hover:opacity-80">drag_indicator</mat-icon>
<span class="text-lg pointer-events-none">
{{ 'PAC.KEY_WORDS.CalculatedFormula' | translate: {Default: 'Calculated Formula'} }}
</span>
<span *ngIf="measure?.caption">({{measure.caption}})</span>
</div>

<div class="flex-1 flex flex-col justify-start items-stretch overflow-hidden">
<ngm-copilot-chat class="flex-1 h-full w-full"></ngm-copilot-chat>
</div>

<div class="flex">
<div ngmButtonGroup>
<button mat-raised-button color="accent" [matDialogClose]="formula">
{{ ('COMPONENTS.COMMON.Apply' | translate: {Default: 'Apply'}) }}
</button>

<button mat-button mat-dialog-close cdkFocusInitial >
{{ ('COMPONENTS.COMMON.CANCEL' | translate: {Default: 'Cancel'}) }}
</button>
</div>
</div>
</div>

<div class="flex-1 flex overflow-hidden">
<ngm-formula-editor *ngIf="syntax === Syntax.SQL" class="flex w-full h-full"
[dataSettings]="dataSettings"
[(ngModel)]="formula"
>
</ngm-formula-editor>
<ngm-calculated-measure *ngIf="syntax === Syntax.MDX" class="flex w-full h-full"
[syntax]="Syntax.MDX"
[dataSettings]="dataSettings"
[entityType]="entityType"
[(ngModel)]="formula"
>
</ngm-calculated-measure>
<div class="flex-1 flex overflow-hidden">
<ngm-formula-editor *ngIf="syntax === Syntax.SQL" class="flex w-full h-full"
[editorOptions]="{
theme: themeName()
}"
[dataSettings]="dataSettings"
[(ngModel)]="formula"
>
</ngm-formula-editor>
<ngm-calculated-measure *ngIf="syntax === Syntax.MDX" class="flex w-full h-full"
[theme]="themeName()"
[syntax]="Syntax.MDX"
[dataSettings]="dataSettings"
[entityType]="entityType"
[(ngModel)]="formula"
>
</ngm-calculated-measure>
</div>
</div>
4 changes: 4 additions & 0 deletions apps/cloud/src/app/@shared/model/formula.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@
flex: 1;
max-width: 100%;
overflow: hidden;
}

.ngm-copilot-chat {
--ngm-copilot-bg-color: theme('colors.bluegray.700');
}
86 changes: 62 additions & 24 deletions apps/cloud/src/app/@shared/model/formula.component.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, Inject, Input } from '@angular/core'
import { ChangeDetectionStrategy, Component, Inject, Input, inject } from '@angular/core'
import { toSignal } from '@angular/core/rxjs-interop'
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MAT_DIALOG_DATA } from '@angular/material/dialog'
import { NgmSearchComponent } from '@metad/ocap-angular/common'
import { CalculatedMeasureComponent } from '@metad/components/property'
import { NgmCopilotChatComponent, NgmCopilotEngineService, injectCopilotCommand, injectMakeCopilotActionable } from '@metad/ocap-angular/copilot'
import { ButtonGroupDirective } from '@metad/ocap-angular/core'
import { FormulaModule } from '@metad/ocap-angular/formula'
import { DataSettings, EntityType, PropertyMeasure, Syntax } from '@metad/ocap-core'
import { TranslateModule } from '@ngx-translate/core'
import { HighlightDirective } from '@metad/components/core'
import { MDXReference } from '@metad/components/mdx'
import { CalculatedMeasureComponent } from '@metad/components/property'
import { sortBy } from 'lodash-es'
import { MarkdownModule } from 'ngx-markdown'
import { map, of, startWith, switchMap } from 'rxjs'
import { Store } from '../../@core'
import { MaterialModule } from '../material.module'
import { NGXLogger } from 'ngx-logger'

@Component({
standalone: true,
Expand All @@ -24,20 +22,21 @@ import { MaterialModule } from '../material.module'
TranslateModule,
MaterialModule,
FormulaModule,
MarkdownModule,
HighlightDirective,
CalculatedMeasureComponent,
ButtonGroupDirective,
NgmSearchComponent
NgmCopilotChatComponent
],
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'pac-model-formula',
templateUrl: 'formula.component.html',
styleUrls: ['formula.component.scss']
styleUrls: ['formula.component.scss'],
providers: [ NgmCopilotEngineService ]
})
export class ModelFormulaComponent {
readonly #store = inject(Store)
readonly #logger = inject(NGXLogger)

Syntax = Syntax
FUNCTIONS = sortBy(MDXReference.FUNCTIONS, 'label')

@Input() dataSettings: DataSettings
@Input() entityType: EntityType
Expand All @@ -54,17 +53,56 @@ export class ModelFormulaComponent {

formula = ''

public readonly functions$ = of(sortBy(MDXReference.FUNCTIONS, 'label')).pipe(
switchMap((functions) =>
this.searchControl.valueChanges.pipe(
startWith(''),
map((text) => {
text = text?.trim().toLowerCase()
return text ? functions.filter((item) => item.label.toLowerCase().includes(text)) : functions
})
)
)
)
readonly themeName = toSignal(this.#store.primaryTheme$)

#newFormula = injectMakeCopilotActionable({
name: 'new_formula',
description: 'New formula for measure',
argumentAnnotations: [
{
name: 'formula',
type: 'string',
description: 'The formula to be used for the measure',
required: true
}
],
implementation: async (formula: string) => {
this.#logger.debug(`Copilot make formula is: ${formula}`)
this.formula = formula
return `The formula for the measure has been set to: ${formula}`
}
})

#formatFormula = injectCopilotCommand({
name: 'format',
description: '',
systemPrompt: () => {
return `Format the MDX formula:
\`\`\`
${this.formula}
\`\`\`
`
},
actions: [
injectMakeCopilotActionable({
name: 'format_formula',
description: 'Format the formula',
argumentAnnotations: [
{
name: 'formula',
type: 'string',
description: 'The formula to be formatted',
required: true
}
],
implementation: async (formula: string) => {
this.#logger.debug('Copilot format formula')
this.formula = formula
return `The formula has been formatted`
}
})
]
})

constructor(
@Inject(MAT_DIALOG_DATA)
Expand Down

0 comments on commit bd7b17d

Please sign in to comment.