humainflow-web/src/app/shared/task-execution-inputs-panel/task-execution-inputs-panel...

172 lines
6.4 KiB
HTML

<div class="p-3 space-y-3">
@if (authorizationRequirements().length) {
<section class="space-y-3">
<div>
<div class="text-xs font-semibold uppercase tracking-wide text-slate-600">Provider Authorizations</div>
<div class="mt-1 text-[11px] text-slate-500">Provide the missing runtime credentials required by this execution.</div>
</div>
@for (requirement of authorizationRequirements(); track requirement.key) {
<div class="rounded-md border border-amber-200 bg-amber-50 p-3">
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div class="text-xs font-semibold text-slate-800">{{ requirement.provider }}</div>
<div class="mt-1 text-[11px] text-slate-500 break-all">{{ requirement.key }}</div>
</div>
<span class="rounded-full bg-white px-2 py-1 text-[10px] font-semibold uppercase tracking-wide text-amber-700">
{{ requirement.fieldName || 'authorization' }}
</span>
</div>
<div class="mt-2 text-xs text-slate-600">{{ requirement.description || 'Runtime authorization required.' }}</div>
@if (requirement.requiredBySteps.length) {
<div class="mt-2 text-[11px] text-slate-500">
Required by: {{ requirement.requiredBySteps.join(', ') }}
</div>
}
<div class="mt-3 flex items-start gap-2">
<mat-form-field appearance="outline" class="flex-1">
<mat-label>{{ requirement.fieldName || 'Authorization' }}</mat-label>
<input
matInput
[type]="isAuthorizationVisible(requirement.key) ? 'text' : 'password'"
[readonly]="readOnly()"
[ngModel]="authorizationValue(requirement.key)"
(ngModelChange)="onAuthorizationValueChange(requirement, $event)" />
</mat-form-field>
<button
type="button"
mat-stroked-button
class="shrink-0"
[disabled]="readOnly()"
(click)="toggleAuthorizationVisibility(requirement.key, $event)">
{{ isAuthorizationVisible(requirement.key) ? 'Hide' : 'Show' }}
</button>
<button
type="button"
mat-flat-button
class="shrink-0"
[disabled]="!canSubmitAuthorization(requirement.key)"
(click)="submitAuthorization(requirement, $event)">
Save
</button>
</div>
@if (isAuthorizationSaving(requirement.key)) {
<div class="mt-2 text-[11px] text-blue-600">Saving authorization...</div>
}
@if (authorizationSavingError(requirement.key); as errorMessage) {
<div class="mt-2 text-[11px] text-red-600">{{ errorMessage }}</div>
}
</div>
}
</section>
}
@if (!editableInputs().length && !authorizationRequirements().length) {
<div class="text-xs text-slate-500">No manual inputs required.</div>
} @else {
@if (editableInputs().length) {
<div class="text-xs font-semibold uppercase tracking-wide text-slate-600">Manual Inputs</div>
}
@for (executionInput of editableInputs(); track executionInput.key) {
<div class="rounded-md border border-slate-200 bg-slate-50 p-2">
<div class="mb-3 flex min-h-[52px] flex-col items-center justify-center rounded-[10px] border border-blue-200 bg-gradient-to-b from-blue-50 to-blue-100 px-3 py-2 text-center text-blue-700">
<div class="text-[14px] font-extrabold leading-tight">{{ executionInput.title }}</div>
<div class="mt-1 text-[11px] font-semibold uppercase tracking-[0.04em] text-blue-600">{{ executionInput.subtitle }}</div>
</div>
<div class="mb-2 text-[10px] text-slate-500">Type: {{ inputTypeLabel(executionInput) }}</div>
@if (isFileInput(executionInput)) {
<input
type="file"
class="block w-full text-sm text-slate-700"
[attr.multiple]="isMultipleInput(executionInput) ? '' : null"
[disabled]="readOnly()"
(change)="onFileInputChange(executionInput, $event)" />
} @else {
@if (isMultipleInput(executionInput)) {
<div class="space-y-3">
@for (textValue of textValues(executionInput); track $index) {
<div class="flex items-start gap-2">
<mat-form-field appearance="outline" class="flex-1">
<mat-label>{{ executionInput.subtitle }} {{ $index + 1 }}</mat-label>
<textarea
matInput
rows="3"
[readonly]="readOnly()"
[ngModel]="textValue"
(ngModelChange)="updateTextItem(executionInput, $index, $event)">
</textarea>
</mat-form-field>
<button
type="button"
mat-stroked-button
class="shrink-0"
[disabled]="readOnly() || textValues(executionInput).length <= 1"
(click)="removeTextItem(executionInput, $index)">
Remove
</button>
</div>
}
<button
type="button"
mat-stroked-button
[disabled]="readOnly()"
(click)="addTextItem(executionInput)">
Add item
</button>
<div class="flex justify-end">
<button
type="button"
mat-flat-button
[disabled]="!canSubmitTextInput(executionInput)"
(click)="submitTextInput(executionInput, $event)">
Save
</button>
</div>
</div>
} @else {
<div class="space-y-3">
<mat-form-field appearance="outline" class="w-full">
<mat-label>{{ executionInput.subtitle }}</mat-label>
<textarea
matInput
rows="4"
[readonly]="readOnly()"
[ngModel]="executionInput.value"
(ngModelChange)="onTextInputChange(executionInput, $event)">
</textarea>
</mat-form-field>
<div class="flex justify-end">
<button
type="button"
mat-flat-button
[disabled]="!canSubmitTextInput(executionInput)"
(click)="submitTextInput(executionInput, $event)">
Save
</button>
</div>
</div>
}
}
@if (isInputSaving(executionInput.key)) {
<div class="mt-2 text-[11px] text-blue-600">Saving...</div>
}
@if (inputSavingError(executionInput.key); as errorMessage) {
<div class="mt-2 text-[11px] text-red-600">{{ errorMessage }}</div>
}
</div>
}
}
</div>