This commit is contained in:
adm 2024-11-22 15:18:04 +03:00
parent 230a4efccf
commit 7b2b8b08ed
39 changed files with 804 additions and 21 deletions

View File

@ -0,0 +1,36 @@
using domain.Service;
using domain.UseCase;
using Microsoft.AspNetCore.Mvc;
using Presence.Api.Response;
namespace Presence.Api.Controllers
{
[ApiController]
[Route("api/[contrtoller]")]
public class GroupController: ControllerBase
{
private readonly IGroupUseCase _groupService;
public GroupController(IGroupUseCase groupService) {
_groupService = groupService;
}
[HttpGet("/group")]
public ActionResult<GroupResponse> GetAllGroups() {
var result = _groupService
.GetGroupsWithStudents()
.Select(group => new GroupResponse {
Id = group.Id,
Name = group.Name,
Users = group.Users?.Select(
user => new UserResponse {
Guid = user.Guid,
Name = user.Name,
}).Take(10).ToList()
}).ToList();
return Ok(result);
}
}
}

View File

@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Mvc;
namespace Presence.Api.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}

View File

@ -0,0 +1,22 @@
using data;
using data.Repository;
using domain.Service;
using domain.UseCase;
using Presence.Api.Controllers;
namespace Presence.Api.Extensions
{
public static class ServiceCollectionsExtension
{
public static void AddCommonServices(this IServiceCollection services) {
services
.AddDbContext<RemoteDatabaseContext>()
.AddScoped<IGroupRepository, SQLGroupRepository>()
.AddScoped<IGroupUseCase, GroupService>()
.AddScoped<GroupController>();
}
}
}

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\domain\domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Request\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
@Presence.Api_HostAddress = http://localhost:5137
GET {{Presence.Api_HostAddress}}/weatherforecast/
Accept: application/json
###

28
Presence.Api/Program.cs Normal file
View File

@ -0,0 +1,28 @@
using Presence.Api.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddCommonServices();
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59027",
"sslPort": 44338
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5137",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7100;http://localhost:5137",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,10 @@
namespace Presence.Api.Response
{
public class GroupResponse
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<UserResponse>? Users { get; set; } = null;
}
}

View File

@ -0,0 +1,9 @@
namespace Presence.Api.Response
{
public class UserResponse
{
public Guid Guid { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,13 @@
namespace Presence.Api
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,15 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Presence.Desktop.App"
xmlns:local="using:Presence.Desktop"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>

View File

@ -0,0 +1,37 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Microsoft.Extensions.DependencyInjection;
using Presence.Desktop.DI;
using Presence.Desktop.ViewModels;
using Presence.Desktop.Views;
namespace Presence.Desktop
{
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddCommonService();
var services = serviceCollection.BuildServiceProvider();
var mainViewModel = services.GetRequiredService<MainWindowViewModel>();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = mainViewModel,
};
}
base.OnFrameworkInitializationCompleted();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

View File

@ -0,0 +1,26 @@
using data;
using data.Repository;
using domain.Service;
using domain.UseCase;
using Microsoft.Extensions.DependencyInjection;
using Presence.Desktop.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Presence.Desktop.DI
{
public static class ServiceColletionExtensions
{
public static void AddCommonService(this IServiceCollection collection) {
collection
.AddDbContext<RemoteDatabaseContext>()
.AddSingleton<IGroupRepository, SQLGroupRepository>()
.AddTransient<IGroupUseCase, GroupService>()
.AddTransient<MainWindowViewModel>();
}
}
}

View File

@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>
<ItemGroup>
<Folder Include="Models\" />
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.1" />
<PackageReference Include="Avalonia.Desktop" Version="11.2.1" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.1" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.1" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.1">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\data\data.csproj" />
<ProjectReference Include="..\domain\domain.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,24 @@
using Avalonia;
using Avalonia.ReactiveUI;
using System;
namespace Presence.Desktop
{
internal sealed class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace()
.UseReactiveUI();
}
}

View File

@ -0,0 +1,32 @@
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Presence.Desktop.ViewModels;
using System;
namespace Presence.Desktop
{
public class ViewLocator : IDataTemplate
{
public Control? Build(object? param)
{
if (param is null)
return null;
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object? data)
{
return data is ViewModelBase;
}
}
}

View File

@ -0,0 +1,13 @@
using domain.UseCase;
namespace Presence.Desktop.ViewModels
{
public class MainWindowViewModel : ViewModelBase
{
private readonly IGroupUseCase _groupService;
public MainWindowViewModel(IGroupUseCase groupUseCase) {
_groupService = groupUseCase;
}
public string Greeting { get; } = "Welcome to Avalonia!";
}
}

View File

@ -0,0 +1,8 @@
using ReactiveUI;
namespace Presence.Desktop.ViewModels
{
public class ViewModelBase : ReactiveObject
{
}
}

View File

@ -0,0 +1,33 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Presence.Desktop.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Presence.Desktop.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Icon="/Assets/avalonia-logo.ico"
Title="Presence.Desktop">
<Design.DataContext>
<vm:MainWindowViewModel/>
</Design.DataContext>
<DockPanel Background="Azure">
<StackPanel DockPanel.Dock="Bottom">
<TextBlock Text="List ↑" HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Spacing="10"
HorizontalAlignment="Center"
DockPanel.Dock="Top"
Orientation="Horizontal">
<TextBlock Text="Combobox ->"/>
<ComboBox/>
<ComboBox/>
<ComboBox/>
</StackPanel>
<Border>
<ListBox Background="Bisque"/>
</Border>
</DockPanel>
</Window>

View File

@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace Presence.Desktop.Views
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="Presence.Desktop.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

40
console_ui/GroupUI.cs Normal file
View File

@ -0,0 +1,40 @@
using domain.Request;
using domain.Service;
using domain.UseCase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace console_ui
{
class GroupUI
{
private readonly IGroupUseCase _groupService;
public GroupUI(IGroupUseCase groupService)
{
_groupService = groupService;
}
public void AddGroup() {
Console.WriteLine("Введите имя группы");
_groupService.AddGroup(new AddGroupRequest { Name = Console.ReadLine() });
}
public void AddGroupWithStudents() {
Console.WriteLine("Введите имя группы");
AddGroupRequest addGroupRequest = new AddGroupRequest { Name = Console.ReadLine()};
List<AddStudentRequest> addStudentRequests = new List<AddStudentRequest>() {
new AddStudentRequest{StudentName = "123" },
new AddStudentRequest{StudentName = "312" },
new AddStudentRequest{StudentName = "222" },
new AddStudentRequest{StudentName = "444" },
};
AddGroupWithStudentsRequest addGroupWithStudents = new AddGroupWithStudentsRequest {
addGroupRequest = addGroupRequest,
AddStudentRequests = addStudentRequests
};
_groupService.AddGroupWithSutdents(addGroupWithStudents);
}
}
}

View File

@ -1,2 +1,31 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
using console_ui;
using data;
using data.Repository;
using domain.Service;
using domain.UseCase;
using Microsoft.Extensions.DependencyInjection;
void printAllGroups(IGroupRepository groupRepository)
{
foreach (var item in groupRepository.getAllGroup())
{
Console.WriteLine($"{item.Id} {item.Name}");
}
}
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection
.AddDbContext<RemoteDatabaseContext>()
.AddSingleton<IGroupRepository, SQLGroupRepository>()
.AddSingleton<IGroupUseCase, GroupService>()
.AddSingleton<GroupUI>();
var serivceProvider = serviceCollection.BuildServiceProvider();
var groupUi = serivceProvider.GetService<GroupUI>();
groupUi?.AddGroup();

View File

@ -15,9 +15,9 @@ namespace data
optionsBuilder.UseNpgsql("Host=localhost;Port=5432;Password=123;Username=postgres;Database=presence");
}
DbSet<GroupDAO> groups { get;set;}
public DbSet<GroupDAO> groups { get;set;}
DbSet<UserDAO> users { get;set;}
public DbSet<UserDAO> users { get;set;}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{

View File

@ -0,0 +1,17 @@
using data.DAO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace data.Repository
{
public interface IGroupRepository
{
public IEnumerable<GroupDAO> getAllGroup();
public bool addGroup(GroupDAO group);
public bool addGroupWithStudents(GroupDAO groupDAO, IEnumerable<UserDAO> userDAOs);
}
}

View File

@ -0,0 +1,50 @@
using data.DAO;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace data.Repository
{
public class SQLGroupRepository : IGroupRepository
{
private readonly RemoteDatabaseContext _dbContext;
public SQLGroupRepository(RemoteDatabaseContext remoteDatabaseContext) {
_dbContext = remoteDatabaseContext;
}
public bool addGroup(GroupDAO group)
{
_dbContext.groups.Add(group);
return _dbContext.SaveChanges() > 1;
}
public bool addGroupWithStudents(GroupDAO groupDAO, IEnumerable<UserDAO> userDAOs)
{
using var transaction = _dbContext.Database.BeginTransaction();
try {
_dbContext.groups.Add(groupDAO);
_dbContext.SaveChanges();
foreach (var item in userDAOs)
{
item.Group = groupDAO;
_dbContext.users.Add(item);
}
_dbContext.SaveChanges();
transaction.Commit();
return true;
}
catch (Exception ex) {
transaction.Rollback();
}
return false;
}
public IEnumerable<GroupDAO> getAllGroup()
{
return _dbContext.groups.Include(group => group.Users).ToList();
}
}
}

View File

@ -1,6 +0,0 @@
namespace domain;
public class Class1
{
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Entity
{
public class GroupEntity
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<UserEntity>? Users { get; set; } = null;
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Entity
{
public class UserEntity
{
public Guid Guid { get; set; }
public string Name { get; set; }
public GroupEntity Group { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Request
{
public class AddGroupRequest
{
public string Name { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Request
{
public class AddGroupWithStudentsRequest
{
public AddGroupRequest addGroupRequest { get; set; }
public IEnumerable<AddStudentRequest> AddStudentRequests { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Request
{
public class AddStudentRequest
{
public string StudentName { get; set; }
}
}

View File

@ -0,0 +1,59 @@
using data.DAO;
using data.Repository;
using domain.Entity;
using domain.Request;
using domain.UseCase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.Service
{
public class GroupService : IGroupUseCase
{
private readonly IGroupRepository _groupRepository;
public GroupService(IGroupRepository groupRepository)
{
_groupRepository = groupRepository;
}
public void AddGroup(AddGroupRequest addGroupRequest)
{
_groupRepository.addGroup(new GroupDAO { Name = addGroupRequest.Name });
}
public void AddGroupWithSutdents(AddGroupWithStudentsRequest addGroupWithStudents)
{
GroupDAO groupDAO = new GroupDAO { Name = addGroupWithStudents.addGroupRequest.Name };
List<UserDAO> users = addGroupWithStudents
.AddStudentRequests
.Select(it => new UserDAO { Name = it.StudentName })
.ToList();
_groupRepository.addGroupWithStudents(groupDAO, users);
}
public IEnumerable<GroupEntity> GetGroupsWithStudents()
{
return _groupRepository.getAllGroup().Select(
group => new GroupEntity
{
Id = group.Id,
Name = group.Name,
Users = group.Users.Select(
user => new UserEntity
{
Guid = user.Guid,
Name = user.Name,
Group = new GroupEntity
{
Id = group.Id,
Name = group.Name,
}
}).ToList()
}).ToList();
}
}
}

View File

@ -0,0 +1,17 @@
using domain.Entity;
using domain.Request;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace domain.UseCase
{
public interface IGroupUseCase
{
public IEnumerable<GroupEntity> GetGroupsWithStudents();
public void AddGroup(AddGroupRequest addGroupRequest);
public void AddGroupWithSutdents(AddGroupWithStudentsRequest addGroupWithStudents);
}
}

View File

@ -4,6 +4,10 @@
<ProjectReference Include="..\data\data.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Response\" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>

View File

@ -3,31 +3,28 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "data", "data\data.csproj", "{FFE39EC0-DDC4-4670-A991-075ADF2B4C95}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "data", "data\data.csproj", "{FFE39EC0-DDC4-4670-A991-075ADF2B4C95}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "domain", "domain\domain.csproj", "{633650E7-0BAB-49D7-B72A-64A5D5A22E26}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ui", "ui\ui.csproj", "{2CDB8D72-14C6-47D8-9DA0-852E72FE1663}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ui", "ui\ui.csproj", "{2CDB8D72-14C6-47D8-9DA0-852E72FE1663}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "console_ui", "console_ui\console_ui.csproj", "{1DEBFFB8-8F9B-4E2D-881C-A65AE0A206C3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "console_ui", "console_ui\console_ui.csproj", "{1DEBFFB8-8F9B-4E2D-881C-A65AE0A206C3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "domain", "domain\domain.csproj", "{8B7BA538-FFE9-4A67-A48B-0ECC957B2315}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Presence.Desktop", "Presence.Desktop\Presence.Desktop.csproj", "{48DA7873-9A3C-458C-8D52-F9156A3E66A6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Presence.Api", "Presence.Api\Presence.Api.csproj", "{EC8CE801-1EEE-4AC1-808D-BF39A8C20ED9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FFE39EC0-DDC4-4670-A991-075ADF2B4C95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFE39EC0-DDC4-4670-A991-075ADF2B4C95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFE39EC0-DDC4-4670-A991-075ADF2B4C95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFE39EC0-DDC4-4670-A991-075ADF2B4C95}.Release|Any CPU.Build.0 = Release|Any CPU
{633650E7-0BAB-49D7-B72A-64A5D5A22E26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{633650E7-0BAB-49D7-B72A-64A5D5A22E26}.Debug|Any CPU.Build.0 = Debug|Any CPU
{633650E7-0BAB-49D7-B72A-64A5D5A22E26}.Release|Any CPU.ActiveCfg = Release|Any CPU
{633650E7-0BAB-49D7-B72A-64A5D5A22E26}.Release|Any CPU.Build.0 = Release|Any CPU
{2CDB8D72-14C6-47D8-9DA0-852E72FE1663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2CDB8D72-14C6-47D8-9DA0-852E72FE1663}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CDB8D72-14C6-47D8-9DA0-852E72FE1663}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -36,5 +33,23 @@ Global
{1DEBFFB8-8F9B-4E2D-881C-A65AE0A206C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1DEBFFB8-8F9B-4E2D-881C-A65AE0A206C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1DEBFFB8-8F9B-4E2D-881C-A65AE0A206C3}.Release|Any CPU.Build.0 = Release|Any CPU
{8B7BA538-FFE9-4A67-A48B-0ECC957B2315}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B7BA538-FFE9-4A67-A48B-0ECC957B2315}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B7BA538-FFE9-4A67-A48B-0ECC957B2315}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B7BA538-FFE9-4A67-A48B-0ECC957B2315}.Release|Any CPU.Build.0 = Release|Any CPU
{48DA7873-9A3C-458C-8D52-F9156A3E66A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48DA7873-9A3C-458C-8D52-F9156A3E66A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48DA7873-9A3C-458C-8D52-F9156A3E66A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48DA7873-9A3C-458C-8D52-F9156A3E66A6}.Release|Any CPU.Build.0 = Release|Any CPU
{EC8CE801-1EEE-4AC1-808D-BF39A8C20ED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EC8CE801-1EEE-4AC1-808D-BF39A8C20ED9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EC8CE801-1EEE-4AC1-808D-BF39A8C20ED9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EC8CE801-1EEE-4AC1-808D-BF39A8C20ED9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {013CA6C5-A281-4520-BCE1-70ACD7E0196A}
EndGlobalSection
EndGlobal