Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
quexy committed Jul 13, 2014
0 parents commit b6c1cf6
Show file tree
Hide file tree
Showing 32 changed files with 2,145 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
wiki/
External/
packages/
*.user
*.suo
bin/
obj/
15 changes: 15 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Repository activity graph generator and host plugin for SpecLog
Copyright (C) 2014 M�ty�s Kab�di <[email protected]>

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 3 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 <http://www.gnu.org/licenses/>.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# SpecLog Graph Plugin
*Repository Activity Graph for SpecLog*


### About
This plugin was created in early 2014, when SpecLog 1.13's features were implemented, as a proof of concept to use SpecLog as a tool to help Project Owners, Scrum Masters, Project Managers and whatever you call them to collect various benchmarks of the work based on the activity of the SpecLog project repository.

The plugin &ndash; as usually SpecLog plugins do &ndash; comprises from a client (configuration interface) and a server (actual behaviour) part. The installer deploys only that half of the plugin which the current SpecLog installation requires, that is, if the server part of SpecLog was installer, then the server side of the plugin will not be deployed.


### Graphs
Currently the plugin makes two types of graph available, a 30-day change frequency graph and a lifetime change GitHub-style punchcard graph. These graphs are available directly from the speclog server as simple HTML pages, not unlike the repository HTML export. The plugin supports a single user basic authentication to restrict access to the generated graphs.


### Configuration
From the SpecLog client menu select the `Manage repositories` menu item, connect to your server.
> !['Manage repositories' menu option](https://raw.githubusercontent.com/wiki/quexy/SpecLog.GraphPlugin/images/manage-repo-menu.png)

Pick a project for which you want to configure the plugin from the list, then click on the `Configure plugins` option.
> !['Configure plugins' for a repository](https://raw.githubusercontent.com/wiki/quexy/SpecLog.GraphPlugin/images/plugin-conf-project-screen.png)
In the plugin list choose `Graph Plugin` and select `Configure` from the plugin menu.
> !['Configure' graph plugin](https://raw.githubusercontent.com/wiki/quexy/SpecLog.GraphPlugin/images/plugin-conf-select-screen.png)
On the appearing dialogue you can turn on the plugin (`Enable plugin`) and set up access restriction (`Viewer credentials`) if you so desire, apart from obtaining a URL (`Publish url`; it contains the identifier of the repository) for accessing the generated graphs. Please note, that the url is live while the plugin is turned on.
> ![Plugin configuration dialogue](https://raw.githubusercontent.com/wiki/quexy/SpecLog.GraphPlugin/images/plugin-conf-screen.png)

### Notes
To keep historical data, you either need to run the SpecLog upgrade tool with the `-keeepHistory` switch or back up and restore the plugin repository (usually from `%ProgramData%\TechTalk\SpecLog\Plugins`).

You should consider using HTTPS if you turn on access restriction. But then again, you should consider turning on HTTPS regardless. Even so if your SpecLog server is open to the internet. It is safer that way.
37 changes: 37 additions & 0 deletions SpecLog.GraphPlugin.Client/ChangeUserDialogView.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<UserControl x:Class="SpecLog.GraphPlugin.Client.ChangeUserDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<DockPanel Margin="10" Width="300">
<StackPanel DockPanel.Dock="Bottom" HorizontalAlignment="Right" Orientation="Horizontal">
<Button Content="OK" Command="{Binding ConfirmCommand}" Margin="0,0,2,0" />
<Button Content="Cancel" Command="{Binding CancelCommand}" Margin="2,0,0,0" />
</StackPanel>
<Grid Margin="0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>

<!-- user name -->
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Text="User name" />
<TextBox Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" Text="{Binding UserName}"/>

<!-- password -->
<TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Text="Password" />
<PasswordBox Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" PasswordChanged="PasswordChanged" Name="PasswordBox" />

<!-- confirm password -->
<TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Text="Confirm password" />
<PasswordBox Grid.Row="2" Grid.Column="2" VerticalAlignment="Center" PasswordChanged="PasswordChanged" Name="ConfirmPwdBox" />
</Grid>
</DockPanel>
</UserControl>
26 changes: 26 additions & 0 deletions SpecLog.GraphPlugin.Client/ChangeUserDialogView.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Windows;
using System.Windows.Controls;

namespace SpecLog.GraphPlugin.Client
{
/// <summary>
/// Interaction logic for ChangeUserDialogView.xaml
/// </summary>
public partial class ChangeUserDialogView : UserControl
{
public ChangeUserDialogView()
{
InitializeComponent();
}

private void PasswordChanged(object sender, RoutedEventArgs e)
{
var viewModel = DataContext as ChangeUserDialogViewModel;
if (viewModel == null) return;

viewModel.Password = PasswordBox.Password;
viewModel.ConfirmPwd = ConfirmPwdBox.Password;
}
}
}
80 changes: 80 additions & 0 deletions SpecLog.GraphPlugin.Client/ChangeUserDialogViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using TechTalk.SpecLog.Application.Common;
using TechTalk.SpecLog.Application.Common.Dialogs;
using TechTalk.SpecLog.Common;

namespace SpecLog.GraphPlugin.Client
{
public class ChangeUserDialogViewModel : IDialogViewModel
{
public event EventHandler<EventArgs<bool?>> Close = delegate { };
public ChangeUserDialogViewModel(string userName)
{
ConfirmCommand = new DelegateCommand(Confirm, CanConfirm);
CancelCommand = new DelegateCommand(Cancel);
UserName = userName;
}

public string Caption
{
get { return "Change user"; }
}

private string userName;
public string UserName
{
get { return userName; }
set { userName = value; ConfirmCommand.RaiseCanExecuteChanged(); }
}

private string password;
public string Password
{
get { return password; }
set { password = value; ConfirmCommand.RaiseCanExecuteChanged(); }
}

private string confirmPwd;
public string ConfirmPwd
{
get { return confirmPwd; }
set { confirmPwd = value; ConfirmCommand.RaiseCanExecuteChanged(); }
}


public IDialogResult GetDialogResultData()
{
return new ChangeUserDialogResult(UserName, Password);
}

public DelegateCommand ConfirmCommand { get; private set; }
public void Confirm()
{
Close(this, new EventArgs<bool?>(true));
}
public bool CanConfirm()
{
return !string.IsNullOrWhiteSpace(UserName)
&& !string.IsNullOrWhiteSpace(Password)
&& string.Equals(Password, ConfirmPwd);
}

public DelegateCommand CancelCommand { get; private set; }
public void Cancel()
{
Close(this, new EventArgs<bool?>(false));
}
}

public class ChangeUserDialogResult : IDialogResult
{
public ChangeUserDialogResult(string userName, string password)
{
UserName = userName;
Password = password;
}

public string UserName { get; set; }
public string Password { get; set; }
}
}
90 changes: 90 additions & 0 deletions SpecLog.GraphPlugin.Client/GraphPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using TechTalk.SpecLog.Application.Common.Dialogs;
using TechTalk.SpecLog.Application.Common.PluginsInfrastructure;
using TechTalk.SpecLog.Common;
using TechTalk.SpecLog.Entities;

namespace SpecLog.GraphPlugin.Client
{
[Plugin(GraphPlugin.PluginName)]
public class GraphPlugin : IClientPlugin, IRepositoryAwareConfiguration
{
public const string PluginName = "SpecLog.GraphPlugin";

private readonly IDialogService dialogService;
public GraphPlugin(IDialogService dialogService)
{
this.dialogService = dialogService;
}

public string Name
{
get { return PluginName; }
}

public string DisplayName
{
get { return "Graph Plugin"; }
}

public string Description
{
get { return "Periodically generates various HTML graphs and makes them available through a simple web server."; }
}

public string LearnMoreLink
{
get { return "http://github.com/quexy/SpecLog.GraphPlugin/"; }
}

public string LearnMoreLinkText
{
get { return "Learn more..."; }
}

public bool IsConfigurable(RepositoryMode repositoryMode)
{
return repositoryMode == RepositoryMode.ClientServer;
}

public IDialogViewModel GetConfigDialog(RepositoryMode repositoryMode, bool isEnabled, string configuration)
{
return GetConfigDialog(null, isEnabled, configuration);
}
public IDialogViewModel GetConfigDialog(IRepositoryInfo repository, bool isEnabled, string configuration)
{
return new GraphPluginConfigDialogViewModel(dialogService, repository, configuration, isEnabled);
}

public bool IsGherkinLinkProvider(RepositoryMode repositoryMode)
{
return false;
}

public IGherkinLinkProviderViewModel GetGherkinLinkViewModel(RepositoryMode repositoryMode)
{
return null;
}

public bool IsGherkinStatsProvider(RepositoryMode repositoryMode)
{
return false;
}

public IGherkinStatsProvider CreateStatsProvider(RepositoryMode repositoryMode, string configuration, IGherkinStatsRepository statsRepository)
{
return null;
}

public bool IsWorkItemSynchronizer(RepositoryMode repositorMode)
{
return false;
}

public IEnumerable<PluginCommand> GetSupportedCommands(RepositoryMode repositoryMode)
{
return new[] { new PluginCommand { CommandVerb = GraphPluginConfiguration.GenerateGraphsVerb, DisplayText = "Generate Graphs" } };
}
}
}
67 changes: 67 additions & 0 deletions SpecLog.GraphPlugin.Client/GraphPluginConfigDialogView.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<UserControl x:Class="SpecLog.GraphPlugin.Client.GraphPluginConfigDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" d:DesignHeight="200" d:DesignWidth="450">
<DockPanel Margin="10" HorizontalAlignment="Center" VerticalAlignment="Center" Width="350">
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" >
<Button Command="{Binding SaveCommand}" Content="Save" Width="50" Margin="0,0,2,0" />
<Button Command="{Binding CancelCommand}" Content="Cancel" Width="50" Margin="2,0,0,0" />
</StackPanel>

<Grid Margin="0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="5" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>

<TextBlock Grid.Row="0" Grid.Column="0" Text="Enable plugin" VerticalAlignment="Center" />
<CheckBox Grid.Row="0" Grid.Column="2" IsChecked="{Binding IsEnabled}" VerticalAlignment="Center" />

<TextBlock Grid.Row="1" Grid.Column="0" Text="Graph refresh period" VerticalAlignment="Center" />
<TextBox Grid.Row="1" Grid.Column="2" Text="{Binding GraphRefreshPeriod}" VerticalAlignment="Center" />

<TextBlock Grid.Row="2" Grid.Column="0" Text="Restict access" VerticalAlignment="Center" />
<CheckBox Grid.Row="2" Grid.Column="2" IsChecked="{Binding IsRestricted}" VerticalAlignment="Center" />

<TextBlock Grid.Row="3" Grid.Column="0" Text="Viewer credentials" VerticalAlignment="Center" IsEnabled="{Binding IsRestricted}" />
<DockPanel Grid.Row="3" Grid.Column="2" VerticalAlignment="Center" IsEnabled="{Binding IsRestricted}">
<Button DockPanel.Dock="Right" Content="Change" Command="{Binding ChangeCredentialsCommand}" Margin="2,0,0,0" />
<Button DockPanel.Dock="Right" Content="Clear" Command="{Binding ClearCredentialsCommand}" Visibility="{Binding ClearButtonVisibility}" Margin="2,0,0,0" />
<Border Padding="2" BorderBrush="#bbbbbb" BorderThickness="1">
<ContentControl Content="{Binding UserName, Mode=OneWay}" VerticalAlignment="Center">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<TextBlock x:Name="username" Text="{TemplateBinding Content}" />
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="username" Property="Foreground" Value="#555555" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
</Border>
</DockPanel>

<TextBlock Grid.Row="5" Grid.Column="0" Text="Publish url" VerticalAlignment="Center" />
<DockPanel Grid.Row="5" Grid.Column="2" VerticalAlignment="Center">
<Button Command="{Binding CopyPublishUrlCommand}" DockPanel.Dock="Right" SnapsToDevicePixels="True" Margin="2,0,0,0">
<Image Source="ToClipboard.png" Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center" SnapsToDevicePixels="True" />
</Button>
<TextBox x:Name="publishUrl" Text="{Binding PublishUrl, Mode=OneWay}" VerticalAlignment="Center" IsReadOnly="True" Foreground="#555555" GotFocus="PublishUrlGotFocus" />
</DockPanel>

</Grid>
</DockPanel>
</UserControl>
32 changes: 32 additions & 0 deletions SpecLog.GraphPlugin.Client/GraphPluginConfigDialogView.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SpecLog.GraphPlugin.Client
{
/// <summary>
/// Interaction logic for GraphPluginConfigDialogView.xaml
/// </summary>
public partial class GraphPluginConfigDialogView : UserControl
{
public GraphPluginConfigDialogView()
{
InitializeComponent();
}

private void PublishUrlGotFocus(object sender, RoutedEventArgs e)
{
publishUrl.SelectAll();
}
}
}
Loading

0 comments on commit b6c1cf6

Please sign in to comment.