feat(settings): add first-run Settings dialog and ribbon entry
- SettingsDialog (WPF, RTL): General tab (URL/username/API key/locale) + About tab; PasswordBox-bound API key, Test Connection probe, Save/Cancel - SettingsViewModel: loads from SettingsManager + DpapiCredentialStore, Test Connection spins a transient HttpClient + EspoCrmClient and reports 401 vs network failures separately; Save persists then signals dialog close - Ribbon: second "הגדרות" button in Marcus-Law group; "File to EspoCRM" now offers to open Settings inline when not configured - AddInHost.LaunchSettings tears down and rebuilds CRM/filing/retry stack so new credentials take effect immediately (CrmClientChanged event) - Tag .taskmaster/tasks/tasks.json: Task #3 in-review with implementation notes (was already locally modified) Core/UI/Tests green (38 tests passing); VSTO host project still requires VS Installer Repair to compile locally. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,8 +35,9 @@
|
|||||||
"dependencies": [
|
"dependencies": [
|
||||||
2
|
2
|
||||||
],
|
],
|
||||||
"status": "pending",
|
"status": "in-review",
|
||||||
"subtasks": []
|
"subtasks": [],
|
||||||
|
"implementationNotes": "Implemented 2026-05-11 (commits e527aa8, 14ed1f6). Deltas from spec: (1) Used MessageBox for summary instead of UWP toast — simpler, can upgrade later. (2) Tests written under OutlookAddin.Tests/Services/ rather than /Core/. (3) Dialog placed in OutlookAddin.UI/Dialogs/ rather than /Views/. (4) Retry queue keeps items on disk after max attempts (3) instead of moving to failed/ — operator can inspect in retry-queue/ folder. (5) MailItem extraction lives in OutlookAddin/Services/MailItemExtractor.cs (host project, since Outlook interop). Build verified for Core/UI/Tests (38 tests green); host project requires VS Installer Repair to compile (VSTO targets still missing on dev machine). Outstanding: first-run settings dialog for credential entry — host shows \"תוסף עדיין לא מוגדר\" if creds.dat absent."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 4,
|
"id": 4,
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
<Window x:Class="MarcusLaw.OutlookAddin.UI.Dialogs.SettingsDialog"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
Title="הגדרות תוסף EspoCRM"
|
||||||
|
Height="520" Width="560"
|
||||||
|
MinHeight="400" MinWidth="500"
|
||||||
|
FlowDirection="RightToLeft"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
ShowInTaskbar="False"
|
||||||
|
ResizeMode="CanResize">
|
||||||
|
<Grid Margin="12">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TabControl Grid.Row="0" x:Name="Tabs">
|
||||||
|
<TabItem Header="כללי">
|
||||||
|
<Grid Margin="8">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="0" Text="כתובת שרת EspoCRM" Margin="0,0,0,2" />
|
||||||
|
<TextBox Grid.Row="1" Text="{Binding EspoCrmUrl, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Padding="6,4" Margin="0,0,0,10" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="2" Text="שם משתמש" Margin="0,0,0,2" />
|
||||||
|
<TextBox Grid.Row="3" Text="{Binding Username, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Padding="6,4" Margin="0,0,0,10" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="4" Text="מפתח API" Margin="0,0,0,2" />
|
||||||
|
<PasswordBox Grid.Row="5" x:Name="ApiKeyBox" Padding="6,4" Margin="0,0,0,10" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="6" Text="שפת ממשק" Margin="0,0,0,2" />
|
||||||
|
<ComboBox Grid.Row="7" SelectedValue="{Binding Locale}" SelectedValuePath="Tag"
|
||||||
|
Padding="6,4" Margin="0,0,0,10">
|
||||||
|
<ComboBoxItem Content="עברית" Tag="he-IL" />
|
||||||
|
<ComboBoxItem Content="English" Tag="en-US" />
|
||||||
|
</ComboBox>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="8" Text="{Binding StatusMessage}"
|
||||||
|
Foreground="{Binding StatusBrush}"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Margin="0,4,0,0" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="9" Orientation="Horizontal" Margin="0,10,0,0">
|
||||||
|
<Button Command="{Binding TestConnectionCommand}"
|
||||||
|
Content="בדוק חיבור"
|
||||||
|
Padding="14,5"
|
||||||
|
MinWidth="120" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem Header="אודות">
|
||||||
|
<StackPanel Margin="16">
|
||||||
|
<TextBlock Text="Marcus-Law OutlookAddin" FontWeight="Bold" FontSize="16" />
|
||||||
|
<TextBlock Text="תוסף EspoCRM ל-Microsoft Outlook" Margin="0,4,0,12" />
|
||||||
|
<TextBlock Text="{Binding VersionLine}" Foreground="Gray" />
|
||||||
|
<TextBlock Margin="0,16,0,0" TextWrapping="Wrap"
|
||||||
|
Text="לוגים: %LOCALAPPDATA%\MarcusLaw\OutlookAddin\logs" />
|
||||||
|
<TextBlock TextWrapping="Wrap"
|
||||||
|
Text="הגדרות: %APPDATA%\MarcusLaw\OutlookAddin\settings.json" />
|
||||||
|
</StackPanel>
|
||||||
|
</TabItem>
|
||||||
|
</TabControl>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,12,0,0">
|
||||||
|
<Button Command="{Binding SaveCommand}"
|
||||||
|
IsDefault="True"
|
||||||
|
Content="שמור"
|
||||||
|
Padding="20,5"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
MinWidth="100" />
|
||||||
|
<Button Command="{Binding CancelCommand}"
|
||||||
|
IsCancel="True"
|
||||||
|
Content="ביטול"
|
||||||
|
Padding="20,5"
|
||||||
|
MinWidth="100" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows;
|
||||||
|
using MarcusLaw.OutlookAddin.UI.ViewModels;
|
||||||
|
|
||||||
|
namespace MarcusLaw.OutlookAddin.UI.Dialogs
|
||||||
|
{
|
||||||
|
public partial class SettingsDialog : Window
|
||||||
|
{
|
||||||
|
private SettingsViewModel? _viewModel;
|
||||||
|
|
||||||
|
public SettingsDialog()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SettingsDialog(SettingsViewModel viewModel) : this()
|
||||||
|
{
|
||||||
|
AttachViewModel(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AttachViewModel(SettingsViewModel viewModel)
|
||||||
|
{
|
||||||
|
if (_viewModel != null)
|
||||||
|
{
|
||||||
|
_viewModel.RequestClose -= OnRequestClose;
|
||||||
|
_viewModel.ApiKeyReader = null;
|
||||||
|
}
|
||||||
|
_viewModel = viewModel ?? throw new ArgumentNullException(nameof(viewModel));
|
||||||
|
DataContext = _viewModel;
|
||||||
|
_viewModel.RequestClose += OnRequestClose;
|
||||||
|
_viewModel.ApiKeyReader = () => ApiKeyBox.Password;
|
||||||
|
if (!string.IsNullOrEmpty(_viewModel.InitialApiKey))
|
||||||
|
{
|
||||||
|
ApiKeyBox.Password = _viewModel.InitialApiKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRequestClose(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
DialogResult = _viewModel?.DialogResult;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,10 @@
|
|||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OutlookAddin.Core\OutlookAddin.Core.csproj" />
|
<ProjectReference Include="..\OutlookAddin.Core\OutlookAddin.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using MarcusLaw.OutlookAddin.Core.Configuration;
|
||||||
|
using MarcusLaw.OutlookAddin.Core.Security;
|
||||||
|
using MarcusLaw.OutlookAddin.Core.Services;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace MarcusLaw.OutlookAddin.UI.ViewModels
|
||||||
|
{
|
||||||
|
public sealed partial class SettingsViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private static readonly Brush NeutralBrush = Brushes.Gray;
|
||||||
|
private static readonly Brush ErrorBrush = Brushes.Firebrick;
|
||||||
|
private static readonly Brush SuccessBrush = Brushes.SeaGreen;
|
||||||
|
|
||||||
|
private readonly AppSettings _settings;
|
||||||
|
private readonly SettingsManager _settingsManager;
|
||||||
|
private readonly DpapiCredentialStore _credentialStore;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string espoCrmUrl = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string username = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string locale = "he-IL";
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string? statusMessage;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private Brush statusBrush = NeutralBrush;
|
||||||
|
|
||||||
|
public string InitialApiKey { get; }
|
||||||
|
|
||||||
|
public string VersionLine { get; }
|
||||||
|
|
||||||
|
public Func<string>? ApiKeyReader { get; set; }
|
||||||
|
|
||||||
|
public bool? DialogResult { get; private set; }
|
||||||
|
|
||||||
|
public event EventHandler? RequestClose;
|
||||||
|
|
||||||
|
public SettingsViewModel(
|
||||||
|
AppSettings settings,
|
||||||
|
SettingsManager settingsManager,
|
||||||
|
DpapiCredentialStore credentialStore,
|
||||||
|
ILogger logger)
|
||||||
|
{
|
||||||
|
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||||
|
_settingsManager = settingsManager ?? throw new ArgumentNullException(nameof(settingsManager));
|
||||||
|
_credentialStore = credentialStore ?? throw new ArgumentNullException(nameof(credentialStore));
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
|
||||||
|
EspoCrmUrl = settings.EspoCrmUrl;
|
||||||
|
Locale = string.IsNullOrWhiteSpace(settings.Locale) ? "he-IL" : settings.Locale;
|
||||||
|
|
||||||
|
var creds = _credentialStore.Load();
|
||||||
|
Username = creds?.Username ?? string.Empty;
|
||||||
|
InitialApiKey = creds?.ApiKey ?? string.Empty;
|
||||||
|
|
||||||
|
var version = typeof(SettingsViewModel).Assembly.GetName().Version?.ToString() ?? "1.0.0";
|
||||||
|
VersionLine = $"גרסה {version}";
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task TestConnectionAsync()
|
||||||
|
{
|
||||||
|
StatusBrush = NeutralBrush;
|
||||||
|
StatusMessage = "בודק חיבור…";
|
||||||
|
|
||||||
|
if (!Uri.TryCreate(EspoCrmUrl, UriKind.Absolute, out var baseUrl))
|
||||||
|
{
|
||||||
|
Fail("כתובת שרת לא תקינה");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiKey = ReadApiKey();
|
||||||
|
if (string.IsNullOrWhiteSpace(Username) || string.IsNullOrWhiteSpace(apiKey))
|
||||||
|
{
|
||||||
|
Fail("יש להזין שם משתמש ומפתח API");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient? http = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
http = new HttpClient { Timeout = TimeSpan.FromSeconds(15) };
|
||||||
|
var probe = new EspoCrmClient(http, baseUrl.ToString(), Username, apiKey, _logger);
|
||||||
|
var user = await probe.TestConnectionAsync().ConfigureAwait(true);
|
||||||
|
Succeed($"התחברות תקינה — משתמש: {user.UserName ?? user.Id}");
|
||||||
|
}
|
||||||
|
catch (EspoCrmAuthorizationException)
|
||||||
|
{
|
||||||
|
Fail("מפתח ה-API או שם המשתמש שגויים");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Warning(ex, "TestConnection failed");
|
||||||
|
Fail("שגיאת חיבור: " + ex.Message);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
http?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Save()
|
||||||
|
{
|
||||||
|
if (!Uri.TryCreate(EspoCrmUrl, UriKind.Absolute, out _))
|
||||||
|
{
|
||||||
|
Fail("כתובת שרת לא תקינה");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var apiKey = ReadApiKey();
|
||||||
|
if (string.IsNullOrWhiteSpace(Username) || string.IsNullOrWhiteSpace(apiKey))
|
||||||
|
{
|
||||||
|
Fail("יש להזין שם משתמש ומפתח API");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_settings.EspoCrmUrl = EspoCrmUrl.TrimEnd('/');
|
||||||
|
_settings.Locale = string.IsNullOrWhiteSpace(Locale) ? "he-IL" : Locale;
|
||||||
|
_settingsManager.Save(_settings);
|
||||||
|
|
||||||
|
_credentialStore.Save(Username.Trim(), apiKey);
|
||||||
|
_logger.Information("Settings saved (user={User}, url={Url})", Username, _settings.EspoCrmUrl);
|
||||||
|
|
||||||
|
DialogResult = true;
|
||||||
|
RequestClose?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, "Settings save failed");
|
||||||
|
Fail("שמירת ההגדרות נכשלה: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Cancel()
|
||||||
|
{
|
||||||
|
DialogResult = false;
|
||||||
|
RequestClose?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ReadApiKey() => ApiKeyReader?.Invoke() ?? string.Empty;
|
||||||
|
|
||||||
|
private void Fail(string message)
|
||||||
|
{
|
||||||
|
StatusBrush = ErrorBrush;
|
||||||
|
StatusMessage = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Succeed(string message)
|
||||||
|
{
|
||||||
|
StatusBrush = SuccessBrush;
|
||||||
|
StatusMessage = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,5 +67,10 @@ namespace OutlookAddin.Ribbon
|
|||||||
{
|
{
|
||||||
_ = Globals.ThisAddIn.AddInHost.LaunchFileToCaseAsync();
|
_ = Globals.ThisAddIn.AddInHost.LaunchFileToCaseAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnOpenSettings(IRibbonControl control)
|
||||||
|
{
|
||||||
|
Globals.ThisAddIn.AddInHost.LaunchSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,13 @@
|
|||||||
imageMso="MeetingForwardToManager"
|
imageMso="MeetingForwardToManager"
|
||||||
onAction="OnFileToEspoCrm"
|
onAction="OnFileToEspoCrm"
|
||||||
getEnabled="OnGetFileToEspoCrmEnabled" />
|
getEnabled="OnGetFileToEspoCrmEnabled" />
|
||||||
|
<button id="OpenEspoCrmSettings"
|
||||||
|
label="הגדרות"
|
||||||
|
screentip="הגדרות תוסף EspoCRM"
|
||||||
|
supertip="עריכת כתובת השרת, שם המשתמש, מפתח ה-API והעדפות נוספות."
|
||||||
|
size="large"
|
||||||
|
imageMso="ServerPropertiesDialog"
|
||||||
|
onAction="OnOpenSettings" />
|
||||||
</group>
|
</group>
|
||||||
</tab>
|
</tab>
|
||||||
</tabs>
|
</tabs>
|
||||||
|
|||||||
@@ -55,18 +55,24 @@ namespace OutlookAddin.Services
|
|||||||
|
|
||||||
public bool IsConfigured => CrmClient != null && FilingService != null;
|
public bool IsConfigured => CrmClient != null && FilingService != null;
|
||||||
|
|
||||||
|
public event EventHandler? CrmClientChanged;
|
||||||
|
|
||||||
private void TryInitializeCrm()
|
private void TryInitializeCrm()
|
||||||
{
|
{
|
||||||
|
DisposeCrmStack();
|
||||||
|
|
||||||
var creds = CredentialStore.Load();
|
var creds = CredentialStore.Load();
|
||||||
if (creds == null || string.IsNullOrWhiteSpace(creds.Username) || string.IsNullOrWhiteSpace(creds.ApiKey))
|
if (creds == null || string.IsNullOrWhiteSpace(creds.Username) || string.IsNullOrWhiteSpace(creds.ApiKey))
|
||||||
{
|
{
|
||||||
Logger.Information("AddInHost: no stored credentials — CRM features disabled until first-run setup");
|
Logger.Information("AddInHost: no stored credentials — CRM features disabled until first-run setup");
|
||||||
|
CrmClientChanged?.Invoke(this, EventArgs.Empty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Uri.TryCreate(Settings.EspoCrmUrl, UriKind.Absolute, out var baseUrl))
|
if (!Uri.TryCreate(Settings.EspoCrmUrl, UriKind.Absolute, out var baseUrl))
|
||||||
{
|
{
|
||||||
Logger.Warning("AddInHost: settings.EspoCrmUrl is not a valid URL: {Url}", Settings.EspoCrmUrl);
|
Logger.Warning("AddInHost: settings.EspoCrmUrl is not a valid URL: {Url}", Settings.EspoCrmUrl);
|
||||||
|
CrmClientChanged?.Invoke(this, EventArgs.Empty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,13 +84,45 @@ namespace OutlookAddin.Services
|
|||||||
_retryProcessor = new RetryQueueProcessor(RetryQueue, CrmClient, Logger);
|
_retryProcessor = new RetryQueueProcessor(RetryQueue, CrmClient, Logger);
|
||||||
_retryProcessor.Start();
|
_retryProcessor.Start();
|
||||||
Logger.Information("AddInHost: CRM client initialized for {BaseUrl}", baseUrl);
|
Logger.Information("AddInHost: CRM client initialized for {BaseUrl}", baseUrl);
|
||||||
|
CrmClientChanged?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Error(ex, "AddInHost: failed to initialize CRM client");
|
Logger.Error(ex, "AddInHost: failed to initialize CRM client");
|
||||||
|
DisposeCrmStack();
|
||||||
|
CrmClientChanged?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DisposeCrmStack()
|
||||||
|
{
|
||||||
|
try { _retryProcessor?.Dispose(); } catch { /* ignore */ }
|
||||||
|
_retryProcessor = null;
|
||||||
|
try { _httpClient?.Dispose(); } catch { /* ignore */ }
|
||||||
|
_httpClient = null;
|
||||||
|
CrmClient = null;
|
||||||
|
FilingService = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Opens the Settings dialog. On Save, tears down and rebuilds the CRM
|
||||||
|
/// client/filing/retry stack so the new credentials take effect immediately.
|
||||||
|
/// </summary>
|
||||||
|
public bool LaunchSettings()
|
||||||
|
{
|
||||||
|
var vm = new SettingsViewModel(Settings, SettingsManager, CredentialStore, Logger);
|
||||||
|
var dialog = new SettingsDialog(vm);
|
||||||
|
var ok = dialog.ShowDialog();
|
||||||
|
if (ok != true) return false;
|
||||||
|
|
||||||
|
// Re-read settings from disk in case fields were normalized.
|
||||||
|
var refreshed = SettingsManager.Load();
|
||||||
|
Settings.EspoCrmUrl = refreshed.EspoCrmUrl;
|
||||||
|
Settings.Locale = refreshed.Locale;
|
||||||
|
TryInitializeCrm();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Entry point invoked by the ribbon "File to EspoCRM" button. Reads the
|
/// Entry point invoked by the ribbon "File to EspoCRM" button. Reads the
|
||||||
/// current Explorer selection, opens the search dialog, files on success,
|
/// current Explorer selection, opens the search dialog, files on success,
|
||||||
@@ -94,12 +132,16 @@ namespace OutlookAddin.Services
|
|||||||
{
|
{
|
||||||
if (!IsConfigured)
|
if (!IsConfigured)
|
||||||
{
|
{
|
||||||
MessageBox.Show(
|
var result = MessageBox.Show(
|
||||||
"התוסף עדיין לא מוגדר. יש להזין כתובת EspoCRM, שם משתמש ומפתח API בהגדרות.",
|
"התוסף עדיין לא מוגדר. לפתוח את חלון ההגדרות עכשיו?",
|
||||||
"Marcus-Law OutlookAddin",
|
"Marcus-Law OutlookAddin",
|
||||||
MessageBoxButton.OK,
|
MessageBoxButton.YesNo,
|
||||||
MessageBoxImage.Information);
|
MessageBoxImage.Information);
|
||||||
return;
|
if (result == MessageBoxResult.Yes)
|
||||||
|
{
|
||||||
|
LaunchSettings();
|
||||||
|
}
|
||||||
|
if (!IsConfigured) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mailItems = ReadCurrentSelection();
|
var mailItems = ReadCurrentSelection();
|
||||||
|
|||||||
Reference in New Issue
Block a user