Deliver each drop to the zone under the cursor (#953)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-09-10 15:28:08 +02:00
1 parent c7b42bee96
commit eb65b16851
63 files changed
+1300 -554

No files matched your search

@@ -74,7 +74,7 @@ else
@T("Documents for the analysis")
</MudText>
<AttachDocuments Name="Document Analysis Files" Layer="@DropLayers.ASSISTANTS" @bind-DocumentPaths="@this.loadedDocumentPaths" CatchAllDocuments="true" UseSmallForm="false" Provider="@this.ProviderSettings"/>
<AttachDocuments Name="Document Analysis Files" @bind-DocumentPaths="@this.loadedDocumentPaths" CatchAllDocuments="true" UseSmallForm="false" Provider="@this.ProviderSettings"/>
</div>
}
else
@@ -128,7 +128,9 @@ else
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyAnalysisRules" Validation="@this.ValidateAnalysisRules" Immediate="@true" Label="@T("Analysis rules")" HelperText="@T("Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="5" AutoGrow="@true" MaxLines="26" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<ReadFileContent Text="@T("Load analysis rules from document")" @bind-FileContent="@this.policyAnalysisRules" Disabled="@this.IsNoPolicySelectedOrProtected"/>
@* No default target for the rule zones: while the policy definition is open, three
zones are in play, so each drop has to be aimed at the one it belongs to. *@
<ReadFileContent Text="@T("Load analysis rules from document")" @bind-FileContent="@this.policyAnalysisRules" EnableDragDrop="true" Disabled="@this.IsNoPolicySelectedOrProtected"/>
<MudJustifiedText Typo="Typo.body1" Class="mt-3">
@T("After the AI has processed all documents, it needs your instructions on how the result should be formatted. Would you like a structured list with keywords or a continuous text? Should the output include emojis or be written in formal business language? You can specify all these preferences in the output rules. There, you can also predefine a desired structure—for example, by using Markdown formatting to define headings, paragraphs, or bullet points.")
@@ -136,7 +138,7 @@ else
<MudTextField T="string" Disabled="@this.IsNoPolicySelectedOrProtected" @bind-Text="@this.policyOutputRules" Validation="@this.ValidateOutputRules" Immediate="@true" Label="@T("Output rules")" HelperText="@T("Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="5" AutoGrow="@true" MaxLines="26" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<ReadFileContent Text="@T("Load output rules from document")" @bind-FileContent="@this.policyOutputRules" Disabled="@this.IsNoPolicySelectedOrProtected"/>
<ReadFileContent Text="@T("Load output rules from document")" @bind-FileContent="@this.policyOutputRules" EnableDragDrop="true" Disabled="@this.IsNoPolicySelectedOrProtected"/>
@if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
{
@@ -153,7 +155,7 @@ else
<MudDivider Style="height: 0.25ch; margin: 1rem 0;" Class="mt-6" />
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.DocumentScanner" HeaderText="@(T("Document selection - Policy") + $": {this.selectedPolicy?.PolicyName}")" IsExpanded="@(this.selectedPolicy?.IsProtected ?? false)">
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.DocumentScanner" HeaderText="@(T("Document selection - Policy") + $": {this.selectedPolicy?.PolicyName}")" IsExpanded="@this.documentSelectionExpanded" ExpandedChanged="@this.DocumentSelectionExpandedChanged">
<MudText Typo="Typo.h5" Class="mb-1">
@T("Policy Description")
</MudText>
@@ -166,7 +168,10 @@ else
@T("Documents for the analysis")
</MudText>
<AttachDocuments Name="Document Analysis Files" Layer="@DropLayers.ASSISTANTS" @bind-DocumentPaths="@this.loadedDocumentPaths" CatchAllDocuments="true" UseSmallForm="false" Provider="@this.ProviderSettings"/>
@* The whole assistant catches drops, but only while this panel is the open one. A
collapsed panel keeps its content in the DOM with a height of zero, so without this
the invisible zone would swallow the drops meant for the policy definition. *@
<AttachDocuments Name="Document Analysis Files" @bind-DocumentPaths="@this.loadedDocumentPaths" CatchAllDocuments="@this.documentSelectionExpanded" UseSmallForm="false" Provider="@this.ProviderSettings"/>
</ExpansionPanel>
</MudExpansionPanels>
@@ -244,6 +244,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
}
this.policyDefinitionExpanded = !this.selectedPolicy?.IsProtected ?? true;
this.documentSelectionExpanded = !this.policyDefinitionExpanded;
await base.OnInitializedAsync();
this.ApplyFilters([], [ Event.CONFIGURATION_CHANGED, Event.PLUGINS_RELOADED ]);
this.UpdateProviders();
@@ -285,6 +286,17 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
private bool policyIsProtected;
private bool policyHidePolicyDefinition;
private bool policyDefinitionExpanded;
/// <summary>
/// Whether the document selection panel is the open one.
/// </summary>
/// <remarks>
/// Only one of the two panels is ever open, so this is normally the opposite of the field above
/// -- but not always: the user can collapse both. It is tracked rather than derived because it
/// decides whether the document zone is the default target of the whole assistant, and a
/// collapsed zone must not hold that role.
/// </remarks>
private bool documentSelectionExpanded;
private string policyName = string.Empty;
private string policyDescription = string.Empty;
private string policyAnalysisRules = string.Empty;
@@ -333,7 +345,11 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
state.Restore(SELECTED_POLICY_STATE_KEY, value => this.selectedPolicy = value);
state.Restore(POLICY_IS_PROTECTED_STATE_KEY, value => this.policyIsProtected = value);
state.Restore(POLICY_HIDE_POLICY_DEFINITION_STATE_KEY, value => this.policyHidePolicyDefinition = value);
state.Restore(POLICY_DEFINITION_EXPANDED_STATE_KEY, value => this.policyDefinitionExpanded = value);
state.Restore(POLICY_DEFINITION_EXPANDED_STATE_KEY, value =>
{
this.policyDefinitionExpanded = value;
this.documentSelectionExpanded = !value;
});
state.Restore(POLICY_NAME_STATE_KEY, value => this.policyName = value);
state.Restore(POLICY_DESCRIPTION_STATE_KEY, value => this.policyDescription = value);
state.Restore(POLICY_ANALYSIS_RULES_STATE_KEY, value => this.policyAnalysisRules = value);
@@ -359,6 +375,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
this.selectedPolicy = policy;
this.ResetForm();
this.policyDefinitionExpanded = !this.selectedPolicy?.IsProtected ?? true;
this.documentSelectionExpanded = !this.policyDefinitionExpanded;
this.ApplyPolicyPreselection(preferPolicyPreselection: true);
this.Form?.ResetValidation();
@@ -368,6 +385,22 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
private Task PolicyDefinitionExpandedChanged(bool isExpanded)
{
this.policyDefinitionExpanded = isExpanded;
// The panels do not allow multi expansion, so opening this one closes the other:
if (isExpanded)
this.documentSelectionExpanded = false;
return Task.CompletedTask;
}
private Task DocumentSelectionExpandedChanged(bool isExpanded)
{
this.documentSelectionExpanded = isExpanded;
// The panels do not allow multi expansion, so opening this one closes the other:
if (isExpanded)
this.policyDefinitionExpanded = false;
return Task.CompletedTask;
}
@@ -457,6 +490,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
this.policyIsProtected = state;
this.selectedPolicy.IsProtected = state;
this.policyDefinitionExpanded = !state;
this.documentSelectionExpanded = state;
await this.AutoSave(true);
}
@@ -634,6 +668,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
// Update the expansion state based on the policy protection:
this.policyDefinitionExpanded = !this.selectedPolicy?.IsProtected ?? true;
this.documentSelectionExpanded = !this.policyDefinitionExpanded;
// Update available providers:
this.UpdateProviders();