Skip to content

Commit

Permalink
fdc3-ClientProfileDemo - demo for fdc3, Channels, SyncContact
Browse files Browse the repository at this point in the history
  • Loading branch information
stanislav-peichev committed Nov 5, 2024
1 parent faa26ae commit 5967e44
Show file tree
Hide file tree
Showing 33 changed files with 2,159 additions and 0 deletions.
43 changes: 43 additions & 0 deletions fdc3-ClientProfileDemo/AGM/CRMServiceOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using DOT.AGM;
using DOT.AGM.Core;
using DOT.AGM.Services;
using Tick42;

namespace FDC3ChannelsClientProfileDemo.AGM
{
// used to modify an invocation
public class CRMServiceOptions : IServiceOptions
{
public CRMServiceOptions(IInstance target)
{
Target = target;
}

public IInstance Target { get; }

public IServerAGMOptions ServerOptions => throw new NotImplementedException();

AgmInvocationContext IServiceOptions.InvocationContext => throw new NotImplementedException();
}

public class CRMServiceOptionsAdapter : IAGMServiceOptionsAdapter<IServiceOptions>
{
public IClientAGMOptions AdaptClientOptions(IAGMProxyService proxyService, IServiceOptions options)
{
var opt = options as CRMServiceOptions;
return new ClientServiceAGMOptions(additionalSettings: new AdditionalSettings
{
// if Target is set, ensure we only call that instance
InvocationPreProcessor = builder => builder.AddServers(
new LambdaInstanceRestriction(
i => opt?.Target?.InstanceId?.Equals(i.InstanceId) != false))
});
}

public IServiceOptions AdaptServerOptions(IAGMService service, IServerAGMOptions serviceOptions)
{
return null;
}
}
}
15 changes: 15 additions & 0 deletions fdc3-ClientProfileDemo/AGM/IT42CRMService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using DOT.AGM.Client;
using DOT.AGM.Services;
using Tick42;
using Tick42.Entities;

namespace FDC3ChannelsClientProfileDemo.AGM
{
[ServiceContract(MethodNamespace = "T42.CRM.")]
public interface IT42CRMService : IDisposable
{
[ServiceOperation(AsyncIfPossible = true, ExceptionSafe = true, InvocationTargetType = MethodTargetType.All)]
void SyncContact(T42Contact contact, [AGMServiceOptions] IServiceOptions options = null);
}
}
64 changes: 64 additions & 0 deletions fdc3-ClientProfileDemo/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="ERROR"/>
<foreColor value="White"/>
<backColor value="Red, HighIntensity"/>
</mapping>
<mapping>
<level value="DEBUG"/>
<foreColor value="Green"/>
</mapping>
<mapping>
<level value="WARN"/>
<foreColor value="Yellow"/>
</mapping>
<mapping>
<level value="TRACE"/>
<foreColor value="Purple"/>
</mapping>
<mapping>
<level value="INFO"/>
<foreColor value="White"/>
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
<root>
<level value="INFO"/>
<appender-ref ref="OutputDebugStringAppender"/>
<appender-ref ref="RollingFileAppender"/>
<!--<appender-ref ref="ColoredConsoleAppender"/>-->
</root>
<appender name="OutputDebugStringAppender" type="log4net.Appender.OutputDebugStringAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString">
<conversionPattern value="${LOCALAPPDATA}\interop.io\io.Connect Desktop\Demos\logs\FDC3ChannelsClientPortfolioDemo.log" />
</file>
<appendToFile value="true"/>
<maximumFileSize value="20MB"/>
<maxSizeRollBackups value="10"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
</log4net>
</configuration>
12 changes: 12 additions & 0 deletions fdc3-ClientProfileDemo/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Application x:Class="FDC3ChannelsClientProfileDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:ClassModifier="internal"
StartupUri="MainWindow.xaml" ShutdownMode="OnLastWindowClose">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="{x:Type Rectangle}" />
<BooleanToVisibilityConverter x:Key="visibilityConverter" />
</ResourceDictionary>
</Application.Resources>
</Application>
193 changes: 193 additions & 0 deletions fdc3-ClientProfileDemo/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#region Tick42 namespaces

using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
using DOT.AGM;
using FDC3ChannelsClientProfileDemo.POCO;
using log4net;
using log4net.Config;
using Tick42;
using Tick42.StartingContext;

#endregion

[assembly: XmlConfigurator(Watch = true)]

namespace FDC3ChannelsClientProfileDemo
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
partial class App : Application
{
static volatile bool isDisposed_;
private ILog logger_;

public static AppMode Mode { get; private set; }
public static bool StickyWindowsEnabled => Utils.IsStickyWindowsEnabled(Mode);
public static bool PortfolioHidden => Utils.IsGlueEnabled(Mode);
public static string GlueUsername { get; private set; }
public static bool UseAlternateLogo { get; private set; }

public static Glue42 Glue { get; private set; }
public static AppState StartupState { get; }
public static string PortfolioAppName { get; private set; }
public static bool DefaultToDarkTheme { get; private set; }
public static string ClientsUrl { get; private set; }

public void Dispose()
{
}

// Lifecycle
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);

// General app logic unrelated to Glue
ConfigureLogging();

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
DispatcherUnhandledException += App_DispatcherUnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;

if (Utils.ForceDebug())
{
Debugger.Break();
}

Mode = Utils.GetAppMode();
DefaultToDarkTheme = Utils.ShouldDefaultToDarkTheme();
PortfolioAppName = Utils.GetArg("portfolio-app-name") ?? "channelsclientportfolio";
ClientsUrl = Utils.GetArg("clients-url") ?? Utils.GetArg("clients") ?? "http://localhost:22060/clients";
UseAlternateLogo = Utils.GetArg("altLogo", "false").Equals("true", StringComparison.OrdinalIgnoreCase);
}

private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
logger_.Error("Unhandled exception: " + e.Exception);
}

private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
logger_.Error("Unhandled exception: " + e.Exception);
}

private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
logger_.Error("Unhandled exception: " + e.ExceptionObject);
}

private void ConfigureLogging()
{
XmlConfigurator.Configure();
logger_ = LogManager.GetLogger("ChannelsClientProfileDemo");
logger_.Info("Starting app in mode " + Mode);
logger_.Info("Arguments: " + Environment.CommandLine);
}

protected override void OnExit(ExitEventArgs e)
{
Exit();
base.OnExit(e);
}

public new static void Exit()
{
if (!isDisposed_)
{
isDisposed_ = true;

Glue?.Shutdown();

foreach (Window window in Current.Windows)
{
try
{
window.Close();
}
catch
{
// ignore
}
}
}
}

internal void InitializeGlue()
{
// initialize Tick42 Interop (AGM) and Metrics components
GlueUsername = Utils.GetArg("user") ?? Utils.GetArg("username") ?? Environment.UserName;
string gluePassword = Utils.GetArg("pass") ?? Utils.GetArg("password") ?? "";
string gatewayUrlOverride = Utils.GetArg("gw") ?? Utils.GetArg("gateway");

// these envvars are expanded in some configuration files
Environment.SetEnvironmentVariable("PROCESSID", Process.GetCurrentProcess().Id + "");
Environment.SetEnvironmentVariable("GW_USERNAME", GlueUsername);
Environment.SetEnvironmentVariable("DEMO_MODE", Mode + "");

var initializeOptions = new InitializeOptions
{
ApplicationName = "ChannelsClientProfileDemo",
IncludedFeatures = GDFeatures.UseAppManager | GDFeatures.UseGlueWindows | GDFeatures.UseGlueWindows |
GDFeatures.UseNotifications | GDFeatures.UseContexts,
Credentials = Tuple.Create(GlueUsername, gluePassword),
GatewayUri = gatewayUrlOverride
};
initializeOptions.SetSaveRestoreStateEndpoint(GetState);

Glue42.InitializeGlue(initializeOptions)
.ContinueWith(glue => Dispatcher.BeginInvoke((Action)(() =>
{
if (glue.Status == TaskStatus.Faulted)
{
// glue init failed - still be visible
GetMainWindow().Visibility = Visibility.Visible;
return;
}

Glue = glue.Result;

if (Glue.GlueWindows == null)
{
GetMainWindow().Visibility = Visibility.Visible;
}

logger_.Info("Initialized Glue Metrics and AGM");

Glue.Metrics?.TrackUserJourneyMetrics(this, trackWindows: true, trackClicks: true);

logger_.Info("Initialized Glue");

//register glue
_ = GetMainWindow().RegisterGlue(Glue);
})));
}

public Task<AppState> GetState(Value value)
{
var tcs = new TaskCompletionSource<AppState>();

Dispatcher.BeginInvoke((Action)(() =>
{
var appState = GetMainWindow()?.GetState();
tcs.TrySetResult(appState);
}));

return tcs.Task;
}

private MainWindow GetMainWindow()
{
return Windows.OfType<MainWindow>().FirstOrDefault();
}
}
}
24 changes: 24 additions & 0 deletions fdc3-ClientProfileDemo/AppMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace FDC3ChannelsClientProfileDemo
{
enum AppMode
{
// "Legacy" WPF app, not sticky, not using Glue
Legacy = 1,

// Sticky but still not using Glue
Sticky = 2,

// Full-blown interop.io application with full Glue capabilities
Glue = 3,

/// <summary>
/// Glue Channels and Glue Windows application
/// </summary>
Channels = 4,

/// <summary>
/// Selected client will be published as an fdc3.contact
/// </summary>
FDC3 = 5,
}
}
Loading

0 comments on commit 5967e44

Please sign in to comment.