From 3bfd54bad3fe057427dd22bc3a91ba82503541b1 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 25 Apr 2018 15:59:12 +0200 Subject: [PATCH] Added a prototype for a new TFS integration. --- .../Entities/Attributes.cs | 34 +++ src/Greenshot.Addon.Tfs/Entities/Item.cs | 41 ++++ src/Greenshot.Addon.Tfs/Entities/Operation.cs | 42 ++++ src/Greenshot.Addon.Tfs/Entities/Value.cs | 41 ++++ .../Entities/WorkItemFields.cs | 38 ++++ .../Entities/WorkItemList.cs | 37 ++++ .../Entities/WorkItemQueryResult.cs | 35 ++++ src/Greenshot.Addon.Tfs/Entities/Workitem.cs | 44 ++++ .../Greenshot.Addon.Tfs.csproj | 198 ++++++++++++++++++ src/Greenshot.Addon.Tfs/ITfsConfiguration.cs | 51 +++++ src/Greenshot.Addon.Tfs/ITfsLanguage.cs | 50 +++++ .../Languages/language_tfsplugin-en-US.xml | 13 ++ .../Properties/AssemblyInfo.cs | 54 +++++ src/Greenshot.Addon.Tfs/TfsClient.cs | 186 ++++++++++++++++ src/Greenshot.Addon.Tfs/TfsDestination.cs | 193 +++++++++++++++++ .../ViewModels/TfsConfigViewModel.cs | 84 ++++++++ .../Views/TfsConfigView.xaml | 26 +++ src/Greenshot.Addon.Tfs/packages.config | 34 +++ src/Greenshot.Addon.Tfs/vsts.png | Bin 0 -> 2107 bytes src/Greenshot.sln | 12 +- 20 files changed, 1212 insertions(+), 1 deletion(-) create mode 100644 src/Greenshot.Addon.Tfs/Entities/Attributes.cs create mode 100644 src/Greenshot.Addon.Tfs/Entities/Item.cs create mode 100644 src/Greenshot.Addon.Tfs/Entities/Operation.cs create mode 100644 src/Greenshot.Addon.Tfs/Entities/Value.cs create mode 100644 src/Greenshot.Addon.Tfs/Entities/WorkItemFields.cs create mode 100644 src/Greenshot.Addon.Tfs/Entities/WorkItemList.cs create mode 100644 src/Greenshot.Addon.Tfs/Entities/WorkItemQueryResult.cs create mode 100644 src/Greenshot.Addon.Tfs/Entities/Workitem.cs create mode 100644 src/Greenshot.Addon.Tfs/Greenshot.Addon.Tfs.csproj create mode 100644 src/Greenshot.Addon.Tfs/ITfsConfiguration.cs create mode 100644 src/Greenshot.Addon.Tfs/ITfsLanguage.cs create mode 100644 src/Greenshot.Addon.Tfs/Languages/language_tfsplugin-en-US.xml create mode 100644 src/Greenshot.Addon.Tfs/Properties/AssemblyInfo.cs create mode 100644 src/Greenshot.Addon.Tfs/TfsClient.cs create mode 100644 src/Greenshot.Addon.Tfs/TfsDestination.cs create mode 100644 src/Greenshot.Addon.Tfs/ViewModels/TfsConfigViewModel.cs create mode 100644 src/Greenshot.Addon.Tfs/Views/TfsConfigView.xaml create mode 100644 src/Greenshot.Addon.Tfs/packages.config create mode 100644 src/Greenshot.Addon.Tfs/vsts.png diff --git a/src/Greenshot.Addon.Tfs/Entities/Attributes.cs b/src/Greenshot.Addon.Tfs/Entities/Attributes.cs new file mode 100644 index 000000000..3238f63f5 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Entities/Attributes.cs @@ -0,0 +1,34 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using Newtonsoft.Json; + +namespace Greenshot.Addon.Tfs.Entities +{ + [JsonObject] + public class Attributes + { + [JsonProperty("comment")] + public string Comment { get; set; } + } +} diff --git a/src/Greenshot.Addon.Tfs/Entities/Item.cs b/src/Greenshot.Addon.Tfs/Entities/Item.cs new file mode 100644 index 000000000..f931b9c12 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Entities/Item.cs @@ -0,0 +1,41 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using System; +using Newtonsoft.Json; + +namespace Greenshot.Addon.Tfs.Entities +{ + /// + /// Container for items returned from the api + /// + [JsonObject] + public class CreateAttachmentResult + { + [JsonProperty("id")] + public string id { get; set; } + + [JsonProperty("url")] + public Uri Url { get; set; } + } +} diff --git a/src/Greenshot.Addon.Tfs/Entities/Operation.cs b/src/Greenshot.Addon.Tfs/Entities/Operation.cs new file mode 100644 index 000000000..4a4de97c4 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Entities/Operation.cs @@ -0,0 +1,42 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using Newtonsoft.Json; + +namespace Greenshot.Addon.Tfs.Entities +{ + /// + /// Container for a test with Extension data + /// + [JsonObject] + public class Operation + { + [JsonProperty("op")] + public string OperationType { get; set; } + + [JsonProperty("path")] + public string Path { get; set; } + [JsonProperty("value")] + public Value Value { get; set; } + } +} diff --git a/src/Greenshot.Addon.Tfs/Entities/Value.cs b/src/Greenshot.Addon.Tfs/Entities/Value.cs new file mode 100644 index 000000000..e541bb75c --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Entities/Value.cs @@ -0,0 +1,41 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using System; +using Newtonsoft.Json; + +namespace Greenshot.Addon.Tfs.Entities +{ + [JsonObject] + public class Value + { + [JsonProperty("rel")] + public string Relation { get; set; } + + [JsonProperty("url")] + public Uri Url { get; set; } + + [JsonProperty("attributes")] + public Attributes Attributes { get; set; } + } +} diff --git a/src/Greenshot.Addon.Tfs/Entities/WorkItemFields.cs b/src/Greenshot.Addon.Tfs/Entities/WorkItemFields.cs new file mode 100644 index 000000000..b4650ee70 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Entities/WorkItemFields.cs @@ -0,0 +1,38 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using System; +using Newtonsoft.Json; + +namespace Greenshot.Addon.Tfs.Entities +{ + [JsonObject] + public class WorkItemFields + { + [JsonProperty("System.Title")] + public string Title { get; set; } + + [JsonProperty("System.WorkItemType")] + public string WorkItemType { get; set; } + } +} diff --git a/src/Greenshot.Addon.Tfs/Entities/WorkItemList.cs b/src/Greenshot.Addon.Tfs/Entities/WorkItemList.cs new file mode 100644 index 000000000..ea99559dd --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Entities/WorkItemList.cs @@ -0,0 +1,37 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Greenshot.Addon.Tfs.Entities +{ + [JsonObject] + public class WorkItemList + { + [JsonProperty("count")] + public int Count { get; set; } + [JsonProperty("value")] + public IList Items { get; set; } + } +} diff --git a/src/Greenshot.Addon.Tfs/Entities/WorkItemQueryResult.cs b/src/Greenshot.Addon.Tfs/Entities/WorkItemQueryResult.cs new file mode 100644 index 000000000..eaad31eb9 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Entities/WorkItemQueryResult.cs @@ -0,0 +1,35 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Greenshot.Addon.Tfs.Entities +{ + [JsonObject] + public class WorkItemQueryResult + { + [JsonProperty("workItems")] + public IList Items { get; set; } + } +} diff --git a/src/Greenshot.Addon.Tfs/Entities/Workitem.cs b/src/Greenshot.Addon.Tfs/Entities/Workitem.cs new file mode 100644 index 000000000..62437aff5 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Entities/Workitem.cs @@ -0,0 +1,44 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using System; +using Newtonsoft.Json; + +namespace Greenshot.Addon.Tfs.Entities +{ + [JsonObject] + public class WorkItem + { + [JsonProperty("id")] + public long Id { get; set; } + + [JsonProperty("rev")] + public int Reversion { get; set; } + + [JsonProperty("url")] + public Uri Url { get; set; } + + [JsonProperty("fields")] + public WorkItemFields Fields { get; set; } + } +} diff --git a/src/Greenshot.Addon.Tfs/Greenshot.Addon.Tfs.csproj b/src/Greenshot.Addon.Tfs/Greenshot.Addon.Tfs.csproj new file mode 100644 index 000000000..9d30ab543 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Greenshot.Addon.Tfs.csproj @@ -0,0 +1,198 @@ + + + + + {8B3643A5-AFED-49FF-8D66-6348FB102EB2} + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Greenshot.Addon.Tfs + Greenshot.Addon.Tfs + v4.5.2 + Properties + False + False + 4 + false + Always + + + + 3.5 + + + + + + + + + {f041c685-eb96-4ed1-9ace-0f5bd836610f} + Greenshot.Gfx + + + {5B924697-4DCD-4F98-85F1-105CB84B7341} + Greenshot.Addons + + + ..\packages\Caliburn.Micro.Core.3.2.0\lib\net45\Caliburn.Micro.dll + + + ..\packages\Caliburn.Micro.3.2.0\lib\net45\Caliburn.Micro.Platform.dll + + + ..\packages\Caliburn.Micro.3.2.0\lib\net45\Caliburn.Micro.Platform.Core.dll + + + ..\packages\CommonServiceLocator.2.0.3\lib\net45\CommonServiceLocator.dll + + + ..\packages\ControlzEx.3.0.2.4\lib\net45\ControlzEx.dll + + + ..\packages\Dapplo.Addons.0.5.56\lib\net45\Dapplo.Addons.dll + + + ..\packages\Dapplo.Addons.Bootstrapper.0.5.56\lib\net45\Dapplo.Addons.Bootstrapper.dll + + + ..\packages\Dapplo.CaliburnMicro.0.5.28\lib\net45\Dapplo.CaliburnMicro.dll + + + ..\packages\Dapplo.CaliburnMicro.Configuration.0.5.28\lib\net45\Dapplo.CaliburnMicro.Configuration.dll + + + ..\packages\Dapplo.CaliburnMicro.Dapp.0.5.28\lib\net45\Dapplo.CaliburnMicro.Dapp.dll + + + ..\packages\Dapplo.CaliburnMicro.Menu.0.5.28\lib\net45\Dapplo.CaliburnMicro.Menu.dll + + + ..\packages\Dapplo.CaliburnMicro.Security.0.5.28\lib\net45\Dapplo.CaliburnMicro.Security.dll + + + ..\packages\Dapplo.CaliburnMicro.Translations.0.5.28\lib\net45\Dapplo.CaliburnMicro.Translations.dll + + + ..\packages\Dapplo.HttpExtensions.0.8.35\lib\net45\Dapplo.HttpExtensions.dll + + + ..\packages\Dapplo.HttpExtensions.JsonNet.0.8.35\lib\net45\Dapplo.HttpExtensions.JsonNet.dll + + + ..\packages\Dapplo.Ini.0.5.24\lib\net45\Dapplo.Ini.dll + + + ..\packages\Dapplo.InterfaceImpl.0.2.12\lib\net45\Dapplo.InterfaceImpl.dll + + + ..\packages\Dapplo.Language.0.5.24\lib\net45\Dapplo.Language.dll + + + ..\packages\Dapplo.Log.1.2.1\lib\net45\Dapplo.Log.dll + + + ..\packages\Dapplo.Utils.1.0.158\lib\net45\Dapplo.Utils.dll + + + ..\packages\Dapplo.Windows.0.5.54\lib\net45\Dapplo.Windows.dll + + + ..\packages\Dapplo.Windows.Common.0.5.54\lib\net45\Dapplo.Windows.Common.dll + + + ..\packages\Dapplo.Windows.DesktopWindowsManager.0.5.54\lib\net45\Dapplo.Windows.DesktopWindowsManager.dll + + + ..\packages\Dapplo.Windows.Dpi.0.5.54\lib\net45\Dapplo.Windows.Dpi.dll + + + ..\packages\Dapplo.Windows.Gdi32.0.5.54\lib\net45\Dapplo.Windows.Gdi32.dll + + + ..\packages\Dapplo.Windows.Input.0.5.54\lib\net45\Dapplo.Windows.Input.dll + + + ..\packages\Dapplo.Windows.Kernel32.0.5.54\lib\net45\Dapplo.Windows.Kernel32.dll + + + ..\packages\Dapplo.Windows.Messages.0.5.54\lib\net45\Dapplo.Windows.Messages.dll + + + ..\packages\Dapplo.Windows.User32.0.5.54\lib\net45\Dapplo.Windows.User32.dll + + + ..\packages\MahApps.Metro.1.6.1\lib\net45\MahApps.Metro.dll + + + ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll + + + ..\packages\System.Reactive.Core.3.1.1\lib\net45\System.Reactive.Core.dll + True + + + ..\packages\System.Reactive.Interfaces.3.1.1\lib\net45\System.Reactive.Interfaces.dll + True + + + ..\packages\System.Reactive.Linq.3.1.1\lib\net45\System.Reactive.Linq.dll + True + + + ..\packages\ControlzEx.3.0.2.4\lib\net45\System.Windows.Interactivity.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + + + +mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)" +copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp" +copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\" +mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)" +copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\" + + + \ No newline at end of file diff --git a/src/Greenshot.Addon.Tfs/ITfsConfiguration.cs b/src/Greenshot.Addon.Tfs/ITfsConfiguration.cs new file mode 100644 index 000000000..c8b9fac76 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/ITfsConfiguration.cs @@ -0,0 +1,51 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +#region Usings + +using System; +using System.ComponentModel; +using Dapplo.Ini; +using Dapplo.Ini.Converters; +using Dapplo.InterfaceImpl.Extensions; +using Greenshot.Addons.Core; + +#endregion + +namespace Greenshot.Addon.Tfs +{ + [IniSection("Tfs")] + [Description("Greenshot Tfs Addon configuration")] + public interface ITfsConfiguration : IIniSection, IDestinationFileConfiguration, ITransactionalProperties, INotifyPropertyChanged + { + [Description("After upload copy OneDrive link to clipboard.")] + [DefaultValue("true")] + bool AfterUploadLinkToClipBoard { get; set; } + + [Description("The URI to your TFS system.")] + Uri TfsUri { get; set; } + + [TypeConverter(typeof(StringEncryptionTypeConverter))] + string ApiKey { get; set; } + } +} \ No newline at end of file diff --git a/src/Greenshot.Addon.Tfs/ITfsLanguage.cs b/src/Greenshot.Addon.Tfs/ITfsLanguage.cs new file mode 100644 index 000000000..a40c99144 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/ITfsLanguage.cs @@ -0,0 +1,50 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +#region Usings + +using System.ComponentModel; +using Dapplo.Language; + +#endregion + +namespace Greenshot.Addon.Tfs +{ + [Language("Tfs")] + public interface ITfsLanguage : ILanguage, INotifyPropertyChanged + { + string CommunicationWait { get; } + + string LabelUrl { get; } + + string LabelApiKey { get; } + + string SettingsTitle { get; } + + string UploadFailure { get; } + + string UploadMenuItem { get; } + + string UsePageLink { get; } + } +} \ No newline at end of file diff --git a/src/Greenshot.Addon.Tfs/Languages/language_tfsplugin-en-US.xml b/src/Greenshot.Addon.Tfs/Languages/language_tfsplugin-en-US.xml new file mode 100644 index 000000000..ea4042b8d --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Languages/language_tfsplugin-en-US.xml @@ -0,0 +1,13 @@ + + + + + Communicating with TFS. Please wait... + Link Type + TFS settings + An error occured while uploading to TFS: + Upload to TFS + Url + Api Key + + \ No newline at end of file diff --git a/src/Greenshot.Addon.Tfs/Properties/AssemblyInfo.cs b/src/Greenshot.Addon.Tfs/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..2b0625fa5 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Properties/AssemblyInfo.cs @@ -0,0 +1,54 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +#region Usings + +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Greenshot.Addon.Tfs")] +[assembly: AssemblyDescription("A plugin to upload screenshots to Tfs")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Greenshot")] +[assembly: AssemblyProduct("Tfs plugin")] +[assembly: AssemblyCopyright("Copyright (C) Greenshot 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. + +[assembly: ComVisible(false)] + +// The assembly version, replaced by build scripts + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyInformationalVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + diff --git a/src/Greenshot.Addon.Tfs/TfsClient.cs b/src/Greenshot.Addon.Tfs/TfsClient.cs new file mode 100644 index 000000000..ed3b7eb40 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/TfsClient.cs @@ -0,0 +1,186 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.Composition; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Dapplo.HttpExtensions; +using Dapplo.HttpExtensions.Factory; +using Dapplo.HttpExtensions.JsonNet; +using Greenshot.Addon.Tfs.Entities; +using Greenshot.Addons.Core; +using Greenshot.Addons.Extensions; +using Greenshot.Addons.Interfaces; +using Newtonsoft.Json.Linq; + +namespace Greenshot.Addon.Tfs +{ + /// + /// This capsulates the TFS api calls + /// + [Export] + public class TfsClient + { + private readonly ICoreConfiguration _coreConfiguration; + private readonly ITfsConfiguration _tfsConfiguration; + private readonly HttpBehaviour _tfsHttpBehaviour; + + [ImportingConstructor] + public TfsClient( + ICoreConfiguration coreConfiguration, + ITfsConfiguration tfsConfiguration, + INetworkConfiguration networkConfiguration) + { + _coreConfiguration = coreConfiguration; + _tfsConfiguration = tfsConfiguration; + + _tfsHttpBehaviour = new HttpBehaviour + { + HttpSettings = networkConfiguration, + JsonSerializer = new JsonNetJsonSerializer() + }; + } + + public bool CanUpdate => _tfsConfiguration.TfsUri != null && !string.IsNullOrEmpty(_tfsConfiguration.ApiKey); + public IDictionary WorkItems { get; } = new Dictionary(); + + public async Task UpdateWorkItems() + { + if (!CanUpdate) + { + return; + } + var workItems = await GetOwnWorkitems(); + foreach (var workItem in workItems.Items) + { + WorkItems[workItem.Id] = workItem; + } + } + /// + /// Retrieve the own workitems + /// + /// WorkItemList + public async Task GetOwnWorkitems() + { + _tfsHttpBehaviour.MakeCurrent(); + Uri apiUri = _tfsConfiguration.TfsUri.AppendSegments("_apis").ExtendQuery("api-version", "3.0"); + var client = HttpClientFactory.Create(_tfsConfiguration.TfsUri).SetBasicAuthorization("", _tfsConfiguration.ApiKey); + + var workitemsQueryUri = apiUri.AppendSegments("wit", "wiql"); + + var wiql = new JObject { { "query", "Select [System.Id] FROM WorkItems WHERE [System.AssignedTo] = @me" } }; + + var queryResult = await client.PostAsync>(workitemsQueryUri, wiql); + if (queryResult.HasError) + { + throw new Exception(queryResult.ErrorResponse); + } + + var workItemsUri = apiUri.AppendSegments("wit", "workItems").ExtendQuery("ids", string.Join(",",queryResult.Response.Items.Select(item => item.Id))); + var result = await client.GetAsAsync>(workItemsUri); + if (result.HasError) + { + throw new Exception(result.ErrorResponse); + } + + return result.Response; + } + + /// + /// See here + /// + /// ISurface to attach + /// + public async Task CreateAttachment(ISurface surface) + { + _tfsHttpBehaviour.MakeCurrent(); + + var client = HttpClientFactory.Create(_tfsConfiguration.TfsUri).SetBasicAuthorization("", _tfsConfiguration.ApiKey); + Uri apiUri = _tfsConfiguration.TfsUri.AppendSegments("_apis").ExtendQuery("api-version", "3.0"); + + var filename = surface.GenerateFilename(_coreConfiguration, _tfsConfiguration); + var attachmentUri = apiUri.AppendSegments("wit", "attachments").ExtendQuery("fileName", filename); + using (var imageStream = new MemoryStream()) + { + surface.WriteToStream(imageStream, _coreConfiguration, _tfsConfiguration); + imageStream.Position = 0; + using (var content = new StreamContent(imageStream)) + { + content.SetContentType("application/octet-stream"); + var createAttachmentresult = await client.PostAsync>(attachmentUri, content); + if (createAttachmentresult.HasError) + { + throw new Exception(createAttachmentresult.ErrorResponse); + } + return createAttachmentresult.Response; + } + } + } + + /// + /// Link the WorkItem and the attachment that was created + /// + /// WorkItem + /// CreateAttachmentResult + /// string with optional comment + public async Task LinkAttachment(WorkItem workItem, CreateAttachmentResult attachmentResult, string comment = "Attached screenshot from Greenshot") + { + _tfsHttpBehaviour.MakeCurrent(); + var client = HttpClientFactory.Create(_tfsConfiguration.TfsUri).SetBasicAuthorization("", _tfsConfiguration.ApiKey); + + Uri apiUri = _tfsConfiguration.TfsUri.AppendSegments("_apis").ExtendQuery("api-version", "3.0"); + // https://docs.microsoft.com/en-us/rest/api/vsts/wit/work%20items/update#add_an_attachment + var linkAttachmentUri = apiUri.AppendSegments("wit", "workItems", workItem.Id); + var linkAttachmentRequest = new List + { + new Operation + { + OperationType = "add", + Path = "/relations/-", + Value = new Value + { + Relation = "AttachedFile", + Url = attachmentResult.Url, + Attributes = new Attributes + { + Comment = comment + } + } + } + }; + + var content = HttpContentFactory.Create(linkAttachmentRequest); + content.SetContentType("application/json-patch+json"); + var result = await client.PatchAsync>(linkAttachmentUri, content); + if (result.HasError) + { + throw new Exception(result.ErrorResponse); + } + } + } +} diff --git a/src/Greenshot.Addon.Tfs/TfsDestination.cs b/src/Greenshot.Addon.Tfs/TfsDestination.cs new file mode 100644 index 000000000..115ffac57 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/TfsDestination.cs @@ -0,0 +1,193 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Drawing; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Dapplo.Addons.Bootstrapper.Resolving; +using Dapplo.Log; +using Greenshot.Addon.Tfs.Entities; +using Greenshot.Addons.Addons; +using Greenshot.Addons.Controls; +using Greenshot.Addons.Core; +using Greenshot.Addons.Interfaces; +using Greenshot.Gfx; + +#endregion + +namespace Greenshot.Addon.Tfs +{ + /// + /// Description of OneDriveDestination. + /// + [Destination("Tfs")] + public class TfsDestination : AbstractDestination + { + private static readonly LogSource Log = new LogSource(); + private readonly ITfsConfiguration _tfsConfiguration; + private readonly ITfsLanguage _tfsLanguage; + private readonly TfsClient _tfsClient; + private readonly WorkItem _workItem; + + [ImportingConstructor] + public TfsDestination( + ITfsConfiguration tfsConfiguration, + ITfsLanguage tfsLanguage, + TfsClient tfsClient) + { + _tfsConfiguration = tfsConfiguration; + _tfsLanguage = tfsLanguage; + _tfsClient = tfsClient; + var ignoreTask = _tfsClient.UpdateWorkItems(); + } + + public TfsDestination( + ITfsConfiguration tfsConfiguration, + ITfsLanguage tfsLanguage, + TfsClient tfsClient, WorkItem workItem) : this(tfsConfiguration, tfsLanguage, tfsClient) + { + _workItem = workItem; + } + + public override bool IsActive => base.IsActive && _tfsClient.CanUpdate; + public override bool IsDynamic => true; + + public override IEnumerable DynamicDestinations() + { + var workitems = _tfsClient.WorkItems.Values; + if (workitems.Count == 0) + { + yield break; + } + foreach (var workitem in workitems) + { + yield return new TfsDestination(_tfsConfiguration, _tfsLanguage, _tfsClient, workitem) + { + CoreConfiguration = CoreConfiguration, + GreenshotLanguage = GreenshotLanguage + }; + } + } + + + public override string Description + { + get + { + if (_workItem?.Fields?.Title == null) + { + return _tfsLanguage.UploadMenuItem; + } + // Format the title of this destination + return _workItem.Id + ": " + _workItem.Fields.Title.Substring(0, Math.Min(20, _workItem.Fields.Title.Length)); + } + } + + public override Bitmap DisplayIcon + { + get + { + // TODO: Optimize this + var embeddedResource = GetType().Assembly.FindEmbeddedResources(@".*vsts\.png").FirstOrDefault(); + using (var bitmapStream = GetType().Assembly.GetEmbeddedResourceAsStream(embeddedResource)) + { + return BitmapHelper.FromStream(bitmapStream); + } + } + } + + public override async Task ExportCaptureAsync(bool manuallyInitiated, ISurface surface, + ICaptureDetails captureDetails) + { + if (_workItem == null) + { + return new ExportInformation(Designation, Description) + { + ExportMade = false + }; + } + var uploadUrl = await Upload(_workItem, surface); + + var exportInformation = new ExportInformation(Designation, Description) + { + ExportMade = uploadUrl != null, + Uri = uploadUrl?.AbsoluteUri + }; + ProcessExport(exportInformation, surface); + return exportInformation; + } + + /// + /// Upload the capture to Tfs + /// + /// WorkItem + /// ISurface + /// Uri + private async Task Upload(WorkItem workItem, ISurface surfaceToUpload) + { + try + { + Uri response; + + var cancellationTokenSource = new CancellationTokenSource(); + using (var pleaseWaitForm = new PleaseWaitForm("OneDrive plug-in", _tfsLanguage.CommunicationWait, + cancellationTokenSource)) + { + pleaseWaitForm.Show(); + try + { + var result = await _tfsClient.CreateAttachment(surfaceToUpload); + await _tfsClient.LinkAttachment(workItem, result); + response = result.Url; + } + finally + { + pleaseWaitForm.Close(); + } + } + + if (_tfsConfiguration.AfterUploadLinkToClipBoard) + { + ClipboardHelper.SetClipboardData(response.ToString()); + } + + return response; + } + catch (Exception e) + { + Log.Error().WriteLine(e, "Error uploading."); + MessageBox.Show(_tfsLanguage.UploadFailure + " " + e.Message); + } + + return null; + } + + } +} \ No newline at end of file diff --git a/src/Greenshot.Addon.Tfs/ViewModels/TfsConfigViewModel.cs b/src/Greenshot.Addon.Tfs/ViewModels/TfsConfigViewModel.cs new file mode 100644 index 000000000..01dc30ba7 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/ViewModels/TfsConfigViewModel.cs @@ -0,0 +1,84 @@ +#region Greenshot GNU General Public License + +// Greenshot - a free and open source screenshot tool +// Copyright (C) 2007-2018 Thomas Braun, Jens Klingen, Robin Krom +// +// For more information see: http://getgreenshot.org/ +// The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 1 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#endregion + +using System.ComponentModel.Composition; +using System.Reactive.Disposables; +using Dapplo.CaliburnMicro.Configuration; +using Dapplo.CaliburnMicro.Extensions; +using Greenshot.Addons; +using Greenshot.Addons.Core; +using Greenshot.Addons.ViewModels; + +namespace Greenshot.Addon.Tfs.ViewModels +{ + [Export(typeof(IConfigScreen))] + public sealed class TfsConfigViewModel : SimpleConfigScreen + { + /// + /// Here all disposables are registered, so we can clean the up + /// + private CompositeDisposable _disposables; + + [Import] + public ITfsConfiguration TfsConfiguration { get; set; } + + [Import] + public ITfsLanguage TfsLanguage { get; set; } + + [Import] + public IGreenshotLanguage GreenshotLanguage { get; set; } + + [Import] + public TfsClient TfsClient { get; private set; } + + [Import] + public FileConfigPartViewModel FileConfigPartViewModel { get; private set; } + + public override void Initialize(IConfig config) + { + FileConfigPartViewModel.DestinationFileConfiguration = TfsConfiguration; + // Prepare disposables + _disposables?.Dispose(); + + // Place this config viewmodel under the Destinations parent + ParentId = nameof(ConfigIds.Destinations); + + // Make sure Commit/Rollback is called on the IUiConfiguration + config.Register(TfsConfiguration); + + // automatically update the DisplayName + _disposables = new CompositeDisposable + { + TfsLanguage.CreateDisplayNameBinding(this, nameof(ITfsLanguage.SettingsTitle)) + }; + base.Initialize(config); + } + + protected override void OnDeactivate(bool close) + { + var ignoreTask = TfsClient.UpdateWorkItems(); + _disposables.Dispose(); + base.OnDeactivate(close); + } + } +} diff --git a/src/Greenshot.Addon.Tfs/Views/TfsConfigView.xaml b/src/Greenshot.Addon.Tfs/Views/TfsConfigView.xaml new file mode 100644 index 000000000..b59065d63 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/Views/TfsConfigView.xaml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/src/Greenshot.Addon.Tfs/packages.config b/src/Greenshot.Addon.Tfs/packages.config new file mode 100644 index 000000000..4062a4b64 --- /dev/null +++ b/src/Greenshot.Addon.Tfs/packages.config @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Greenshot.Addon.Tfs/vsts.png b/src/Greenshot.Addon.Tfs/vsts.png new file mode 100644 index 0000000000000000000000000000000000000000..8b3d8c1efe8c721f8a1e48f0d8f9371090127683 GIT binary patch literal 2107 zcmV-B2*me^P)E*cQWdtP zbQYF1XxeR>P&H|c$+VItHPwtUO%-9bRnbQ1>$Vl4Uz*gcwp1a8Y=O$m?oxz>EhvgC z7T9jtrBBR1=7c-2>@qX=&Ya&bdCr|p;L~~XzvrHN&bdPZC0bJ19kdzvZIDhJ2}+!g zfD$bU_&IbULnBNHN|@*?fGWVrAe`4B120n*K2Qblk6G{>>_w0tz<8f3fGR+kURVz+ zp_!_1(k}rdfJ+V<;VBz5>K5P`li+9YF7iA9RX$Y!Re=0#gbchyRp?O#@Q=^KGd5^^ z6h7%w1yBVD(+eA575u>ljUEXg0bE+0L1UM00sb)&erkipC*gXZDu60Le*O#@Xc`tM zK6111xNZS{GcL9Q2)zy#5jSNN{oBZS)ve16z?`R^V+k5AX?SMuJCRXiy=M0IBQ< zNW!aUDe=SbM_WE!wvhm-YyuwRS0}sx)dO4>wG9dG2$b?!6l%}*NoatXP>5vUyR3le z)_Q=rR)AFYMtFi>`{6f*>U?7vZ2n(GiBD7kuzf7;*P#KfgJS0xe1}S~S`{E70c^r% zmUa4FFbYbY=ixp?=qjMhBWWiiS4%kyFsz7XUq-vsI{q4nGK=6QWL$y-n+75A<+N2+ zwXV0{lVE5Gt7!ZMuxIhx;2xN7g2g4DhBuI4IoF>cLSG(fhtp1m>l~_J9Go^1AeH@; zb^149e9VPU!yH6-z$TKaoQ|G65NRbqDtkNa{qUujm%=V+G2XK4gHR8Hi3G3-m)}9$ z(i!UPbmH%M~vyx5Wh$OJHM{60QYNmaQ3et z{*eH5{`s^o!kDwXUvEF9v$xUN$AYqrD!{K`Vi3-M-12R-R?_`i00^G>;fjs*OkOmRJ#AtJV@3sG50nrgL--Byl9=I6;RRE#%Ajmsh0V%+K zx5J)t+F2w4(urRCq|3$uoc%Wf5&)r`K#mTR!NhPXNjmX<5T8f@li)ohsIf7^Wd)FO zf-x7|oJ5Yjr`%TlUr8c5FhT;D1RW;9pI~$m54OD0_+p-M$Ns#x6|Tr}I4FK}R4fuC z?WFIx<w?0P%7X)m;|rUehbPuufPn1-laj{;3RmG_Hj5<{suh|xBM9HK;$Eu2`v1JBbVjS3^h;- z)i460%KLB+@;>F-sMFI`$#j zAKG6F>mcRQ6-E3!xU~3}BFZ6zUP`_xf~fKg9XPkyVCY!)^R^DKx;V{Y*mbff)tu zeBA<~e{qBahhTL-GQ43kd)u`jB>G#y$7#pY8E+N2?4_8Z;ooRC@!~2CdKzZJuoO)MKFS_?-#0un;acQT_|< zt`v~7-8dDr+)Iyv{mT&MAJFCqV!y$ju|+uw5SHOqNWz^k4*E+UbU>@I6LKa;N4abd zmjGcIhSJUs$uKZ_oJ!H=3KI9vze|9y3|}@G7QlsYt~neUZ`f~JOcIMofUpe1Y3GDw zC@k-W#v5Sg27C}i7zq%TVJ<9!8n^(8nO@lKNa3;%IZ9S$B|un)k+juN>&j3+pdIAQ@`mCMcKu6MhN5pwl}F^AsQ%u68QJ4G_n? z39H~GcO`c51dt51Ff|5)y0ws@)3=s>9zZfoa%7kSrAiJOZBTc_kBK13&>yd)