mirror of
https://github.com/EpicMorg/jira-issue-web-reporter.git
synced 2024-12-26 03:45:29 +03:00
public release 1.0.0.17
This commit is contained in:
parent
d2f0294465
commit
8ebaca9759
25
.dockerignore
Normal file
25
.dockerignore
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
**/.classpath
|
||||||
|
**/.dockerignore
|
||||||
|
**/.env
|
||||||
|
**/.git
|
||||||
|
**/.gitignore
|
||||||
|
**/.project
|
||||||
|
**/.settings
|
||||||
|
**/.toolstarget
|
||||||
|
**/.vs
|
||||||
|
**/.vscode
|
||||||
|
**/*.*proj.user
|
||||||
|
**/*.dbmdl
|
||||||
|
**/*.jfm
|
||||||
|
**/azds.yaml
|
||||||
|
**/bin
|
||||||
|
**/charts
|
||||||
|
**/docker-compose*
|
||||||
|
**/Dockerfile*
|
||||||
|
**/node_modules
|
||||||
|
**/npm-debug.log
|
||||||
|
**/obj
|
||||||
|
**/secrets.dev.yaml
|
||||||
|
**/values.dev.yaml
|
||||||
|
LICENSE
|
||||||
|
README.md
|
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
###############################################################################
|
||||||
|
# Set default behavior to automatically normalize line endings.
|
||||||
|
###############################################################################
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set default behavior for command prompt diff.
|
||||||
|
#
|
||||||
|
# This is need for earlier builds of msysgit that does not have it on by
|
||||||
|
# default for csharp files.
|
||||||
|
# Note: This is only used by command line
|
||||||
|
###############################################################################
|
||||||
|
#*.cs diff=csharp
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set the merge driver for project and solution files
|
||||||
|
#
|
||||||
|
# Merging from the command prompt will add diff markers to the files if there
|
||||||
|
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||||
|
# the diff markers are never inserted). Diff markers may cause the following
|
||||||
|
# file extensions to fail to load in VS. An alternative would be to treat
|
||||||
|
# these files as binary and thus will always conflict and require user
|
||||||
|
# intervention with every merge. To do so, just uncomment the entries below
|
||||||
|
###############################################################################
|
||||||
|
#*.sln merge=binary
|
||||||
|
#*.csproj merge=binary
|
||||||
|
#*.vbproj merge=binary
|
||||||
|
#*.vcxproj merge=binary
|
||||||
|
#*.vcproj merge=binary
|
||||||
|
#*.dbproj merge=binary
|
||||||
|
#*.fsproj merge=binary
|
||||||
|
#*.lsproj merge=binary
|
||||||
|
#*.wixproj merge=binary
|
||||||
|
#*.modelproj merge=binary
|
||||||
|
#*.sqlproj merge=binary
|
||||||
|
#*.wwaproj merge=binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# behavior for image files
|
||||||
|
#
|
||||||
|
# image files are treated as binary by default.
|
||||||
|
###############################################################################
|
||||||
|
#*.jpg binary
|
||||||
|
#*.png binary
|
||||||
|
#*.gif binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# diff behavior for common document formats
|
||||||
|
#
|
||||||
|
# Convert binary document formats to text before diffing them. This feature
|
||||||
|
# is only available from the command line. Turn it on by uncommenting the
|
||||||
|
# entries below.
|
||||||
|
###############################################################################
|
||||||
|
#*.doc diff=astextplain
|
||||||
|
#*.DOC diff=astextplain
|
||||||
|
#*.docx diff=astextplain
|
||||||
|
#*.DOCX diff=astextplain
|
||||||
|
#*.dot diff=astextplain
|
||||||
|
#*.DOT diff=astextplain
|
||||||
|
#*.pdf diff=astextplain
|
||||||
|
#*.PDF diff=astextplain
|
||||||
|
#*.rtf diff=astextplain
|
||||||
|
#*.RTF diff=astextplain
|
22
Dockerfile
Normal file
22
Dockerfile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
|
||||||
|
WORKDIR /src-temp
|
||||||
|
COPY ["./src/epicmorg.jira.issue.web.reporter", "jwr/"]
|
||||||
|
RUN dotnet restore "jwr/epicmorg.jira.issue.web.reporter.csproj"
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src-temp/jwr"
|
||||||
|
RUN cat ./epicmorg.jira.issue.web.reporter.csproj && \
|
||||||
|
dotnet build "./epicmorg.jira.issue.web.reporter.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "./epicmorg.jira.issue.web.reporter.csproj" -c Release -o /app/publish
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "epicmorg.jira.issue.web.reporter.dll"]
|
||||||
|
EXPOSE 5000
|
||||||
|
EXPOSE 80
|
5
Makefile
Normal file
5
Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
all: jwr
|
||||||
|
|
||||||
|
jwr:
|
||||||
|
docker build --compress -t epicmorg/jira-issue-web-reporter .
|
||||||
|
docker push epicmorg/jira-issue-web-reporter
|
27
docker-compose.yml
Normal file
27
docker-compose.yml
Normal file
File diff suppressed because one or more lines are too long
25
src/epicmorg.jira.issue.web.reporter.sln
Normal file
25
src/epicmorg.jira.issue.web.reporter.sln
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.29509.3
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "epicmorg.jira.issue.web.reporter", "epicmorg.jira.issue.web.reporter\epicmorg.jira.issue.web.reporter.csproj", "{7C460FFD-D311-47F3-90CC-C42996BBB2DE}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{7C460FFD-D311-47F3-90CC-C42996BBB2DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7C460FFD-D311-47F3-90CC-C42996BBB2DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7C460FFD-D311-47F3-90CC-C42996BBB2DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7C460FFD-D311-47F3-90CC-C42996BBB2DE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {181F5AB3-A6E9-4ABC-AFDB-7E060CEDC759}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
@ -0,0 +1,147 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Controllers
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Captcha;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Check.Request;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Configuration;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Create.Request;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Create.ViewModels;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Services.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
public class HomeController : Controller
|
||||||
|
{
|
||||||
|
private readonly ILogger<HomeController> logger;
|
||||||
|
private readonly UiConfig uiOptions;
|
||||||
|
|
||||||
|
private readonly ICaptchaValidator captchaValidator;
|
||||||
|
private readonly IJiraService jiraService;
|
||||||
|
private readonly JiraConfig jiraConfig;
|
||||||
|
|
||||||
|
public HomeController(
|
||||||
|
ILogger<HomeController> logger,
|
||||||
|
IOptions<UiConfig> uiOptions,
|
||||||
|
IOptions<JiraConfig> jiraConfig,
|
||||||
|
ICaptchaValidator captchaValidator,
|
||||||
|
IJiraService jiraService)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.uiOptions = uiOptions.Value;
|
||||||
|
this.jiraConfig = jiraConfig.Value;
|
||||||
|
|
||||||
|
this.captchaValidator = captchaValidator;
|
||||||
|
this.jiraService = jiraService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IActionResult> Index() => this.View();
|
||||||
|
|
||||||
|
public IActionResult Privacy() => this.View();
|
||||||
|
|
||||||
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
|
public IActionResult Error() => this.View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? this.HttpContext.TraceIdentifier });
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> Create(CancellationToken cancellationToken) => this.View(await this.BuildCreateModel(cancellationToken).ConfigureAwait(false));
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[Route("Check/{id?}")]
|
||||||
|
public async Task<IActionResult> Check(string id = null) => this.View(new CheckRequest { Issue = id});
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
[Route("Check")]
|
||||||
|
public async Task<IActionResult> Check(CheckRequest model, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var valid = await this.IsModelAndCaptchaValid(model, cancellationToken).ConfigureAwait(false);
|
||||||
|
if (!valid)
|
||||||
|
{
|
||||||
|
return this.View(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await this.jiraService.GetIssueStatus(model.Issue, cancellationToken).ConfigureAwait(false);
|
||||||
|
return this.View("CheckResult", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> Create(CreateWebRequest model, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var valid = await this.IsModelAndCaptchaValid(model, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!valid)
|
||||||
|
{
|
||||||
|
var viewModel = await this.BuildCreateModel(cancellationToken, new CreateViewModel(model)).ConfigureAwait(false);
|
||||||
|
return this.View(nameof(this.Create), viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = await this.BuildJiraRequest(model).ConfigureAwait(false);
|
||||||
|
var result = await this.jiraService.CreateIssue(request, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return this.View("Created", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> IsModelAndCaptchaValid(ICaptchaRequest model, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var valid = this.ModelState.IsValid;
|
||||||
|
if (valid)
|
||||||
|
{
|
||||||
|
if (!await this.captchaValidator.Validate(model.Captcha, cancellationToken).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
this.logger.LogInformation($"User has failed captcha");
|
||||||
|
this.ModelState.AddModelError(null, "You failed the CAPTCHA");
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<CreateViewModel> BuildCreateModel(CancellationToken cancellationToken, CreateViewModel model = null)
|
||||||
|
{
|
||||||
|
model ??= new CreateViewModel();
|
||||||
|
model.IssueTypes = new SelectList(
|
||||||
|
items: this.jiraConfig.AllowedIssueTypes,
|
||||||
|
dataValueField: null,
|
||||||
|
dataTextField: null,
|
||||||
|
selectedValue: null);
|
||||||
|
model.Projects = new SelectList(
|
||||||
|
items: await this.jiraService.GetProjects(cancellationToken).ConfigureAwait(false),
|
||||||
|
dataValueField: nameof(ProjectDto.Key),
|
||||||
|
dataTextField: nameof(ProjectDto.Name),
|
||||||
|
selectedValue: null);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<CreateJiraRequest> BuildJiraRequest(CreateWebRequest model)
|
||||||
|
{
|
||||||
|
var request = new CreateJiraRequest(model);
|
||||||
|
var lst = new List<JiraFile>();
|
||||||
|
foreach (var file in model.Files ?? Enumerable.Empty<IFormFile>())
|
||||||
|
{
|
||||||
|
using var stream = file.OpenReadStream();
|
||||||
|
using var ms = new MemoryStream();
|
||||||
|
await stream.CopyToAsync(ms).ConfigureAwait(false);
|
||||||
|
lst.Add(new JiraFile
|
||||||
|
{
|
||||||
|
Name = file.FileName,
|
||||||
|
Content = ms.ToArray(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Files = lst;
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Captcha
|
||||||
|
{
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
public interface ICaptchaRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
[BindProperty(Name = "g-recaptcha-response")]
|
||||||
|
public string Captcha { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Check.Request
|
||||||
|
{
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Captcha;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
public class CheckRequest : ICaptchaRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Issue { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[BindProperty(Name = "g-recaptcha-response")]
|
||||||
|
public string Captcha { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Check.Response
|
||||||
|
{
|
||||||
|
public class CheckResponse
|
||||||
|
{
|
||||||
|
public string Issue { get; set; }
|
||||||
|
|
||||||
|
public bool Success { get; set; }
|
||||||
|
|
||||||
|
public string Resolution { get; set; }
|
||||||
|
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Configuration
|
||||||
|
{
|
||||||
|
public class CaptchaConfig
|
||||||
|
{
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
public string Secret { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Configuration
|
||||||
|
{
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
public class JiraConfig
|
||||||
|
{
|
||||||
|
[Url]
|
||||||
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Login { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string[] AllowedProjects { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string[] AllowedIssueTypes { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Configuration
|
||||||
|
{
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
public class UiConfig
|
||||||
|
{
|
||||||
|
[Url]
|
||||||
|
public string LogoUrl { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string HeaderText { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string DescriptionText { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string LicensedTo { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Theme { get; set; }
|
||||||
|
|
||||||
|
public string GetAssemblyVersion() { return GetType().Assembly.GetName().Version.ToString(); }
|
||||||
|
|
||||||
|
public string GetAssemblyProduct {
|
||||||
|
get {
|
||||||
|
var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
|
||||||
|
return attributes.Length == 0 ? "" : ((AssemblyProductAttribute)attributes[0]).Product.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models
|
||||||
|
{
|
||||||
|
public class JiraFile
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public byte[] Content { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models
|
||||||
|
{
|
||||||
|
public class ProjectDto
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Key { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Create.Request
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class CreateJiraRequest : CreateRequestBase
|
||||||
|
{
|
||||||
|
public CreateJiraRequest() { }
|
||||||
|
|
||||||
|
public CreateJiraRequest(CreateRequestBase source)
|
||||||
|
: base(source) { }
|
||||||
|
|
||||||
|
public IEnumerable<JiraFile> Files { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Create.Request
|
||||||
|
{
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
public class CreateRequestBase
|
||||||
|
{
|
||||||
|
public CreateRequestBase() { }
|
||||||
|
|
||||||
|
public CreateRequestBase(CreateRequestBase source)
|
||||||
|
{
|
||||||
|
this.Description = source.Description;
|
||||||
|
this.Email = source.Email;
|
||||||
|
this.IssueType = source.IssueType;
|
||||||
|
this.Name = source.Name;
|
||||||
|
this.Project = source.Project;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Project { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[EmailAddress]
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string IssueType { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Description { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Create.Request
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Captcha;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
public class CreateWebRequest : CreateRequestBase, ICaptchaRequest
|
||||||
|
{
|
||||||
|
public CreateWebRequest() { }
|
||||||
|
|
||||||
|
public CreateWebRequest(CreateWebRequest source)
|
||||||
|
: base(source)
|
||||||
|
{
|
||||||
|
this.Files = source.Files;
|
||||||
|
this.Captcha = source.Captcha;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[BindProperty(Name = "g-recaptcha-response")]
|
||||||
|
public string Captcha { get; set; }
|
||||||
|
|
||||||
|
public IEnumerable<IFormFile> Files { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Create.Response
|
||||||
|
{
|
||||||
|
public class CreateResponse
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
|
||||||
|
public string IssueKey { get; set; }
|
||||||
|
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models.Create.ViewModels
|
||||||
|
{
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Create.Request;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
|
||||||
|
public class CreateViewModel : CreateWebRequest
|
||||||
|
{
|
||||||
|
public CreateViewModel() { }
|
||||||
|
|
||||||
|
public CreateViewModel(CreateWebRequest source)
|
||||||
|
: base(source) { }
|
||||||
|
|
||||||
|
public SelectList Projects { get; set; }
|
||||||
|
|
||||||
|
public SelectList IssueTypes { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Models
|
||||||
|
{
|
||||||
|
public class ErrorViewModel
|
||||||
|
{
|
||||||
|
public string RequestId { get; set; }
|
||||||
|
|
||||||
|
public bool ShowRequestId => !string.IsNullOrEmpty(this.RequestId);
|
||||||
|
}
|
||||||
|
}
|
14
src/epicmorg.jira.issue.web.reporter/Program.cs
Normal file
14
src/epicmorg.jira.issue.web.reporter/Program.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args) => CreateHostBuilder(args).Build().Run();
|
||||||
|
|
||||||
|
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||||
|
Host.CreateDefaultBuilder(args)
|
||||||
|
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.DI
|
||||||
|
{
|
||||||
|
using Atlassian.Jira;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
public static class AtlassianExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddJira(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddScoped<Jira>(context =>
|
||||||
|
{
|
||||||
|
var jiraOptions = context.GetService<IOptions<JiraConfig>>().Value;
|
||||||
|
var client = Jira.CreateRestClient(
|
||||||
|
jiraOptions.Domain,
|
||||||
|
jiraOptions.Login,
|
||||||
|
jiraOptions.Password,
|
||||||
|
new JiraRestClientSettings
|
||||||
|
{
|
||||||
|
Cache = new Atlassian.Jira.JiraCache(),
|
||||||
|
});
|
||||||
|
return client;
|
||||||
|
});
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.Impl
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Configuration;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Services.Interfaces;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
public class GoogleRecaptchaValidator : ICaptchaValidator
|
||||||
|
{
|
||||||
|
private const string ApiRoot = "https://www.google.com/recaptcha/api/siteverify";
|
||||||
|
|
||||||
|
private readonly HttpClient httpClient;
|
||||||
|
private readonly string secret;
|
||||||
|
private readonly ILogger<GoogleRecaptchaValidator> logger;
|
||||||
|
|
||||||
|
public GoogleRecaptchaValidator(
|
||||||
|
HttpClient httpClient,
|
||||||
|
IOptions<CaptchaConfig> captchaOptions,
|
||||||
|
ILogger<GoogleRecaptchaValidator> logger)
|
||||||
|
{
|
||||||
|
this.httpClient = httpClient;
|
||||||
|
this.secret = captchaOptions.Value.Secret;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> Validate(string response, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var content = new FormUrlEncodedContent(new[]
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, string>("secret", this.secret),
|
||||||
|
new KeyValuePair<string, string>("response", response),
|
||||||
|
});
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var res = await this.httpClient.PostAsync(ApiRoot, content, cancellationToken).ConfigureAwait(false);
|
||||||
|
if (res.StatusCode != HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string jsonResult = await res.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
dynamic jsonData = JObject.Parse(jsonResult);
|
||||||
|
var success = jsonData.success == "true";
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
this.logger.LogInformation("Failed to pass captcha");
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this.logger.LogError(ex, "Failed validate captcha for respose {response}", response);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.Impl
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Check.Response;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Services.Interfaces;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
|
||||||
|
public class JiraCache : JsonCache, IJiraCache
|
||||||
|
{
|
||||||
|
private const string projectsKey = "JiraProjectsKey";
|
||||||
|
|
||||||
|
public JiraCache(IDistributedCache cache)
|
||||||
|
: base(cache) { }
|
||||||
|
|
||||||
|
public Task<IReadOnlyList<ProjectDto>> GetProjects() => this.GetCachedValue<IReadOnlyList<ProjectDto>>(projectsKey);
|
||||||
|
|
||||||
|
public Task SetProjects(IReadOnlyList<ProjectDto> value) => this.SetCachedValue(projectsKey, value, TimeSpan.FromMinutes(1));
|
||||||
|
|
||||||
|
public Task<CheckResponse> GetIssueStatus(string issue) => this.GetCachedValue<CheckResponse>(this.GetIssueKey(issue));
|
||||||
|
|
||||||
|
public Task SetIssue(string issue, CheckResponse value) => this.SetCachedValue(this.GetIssueKey(issue), value, TimeSpan.FromMinutes(1));
|
||||||
|
|
||||||
|
private string GetIssueKey(string issue) => $"JiraIssue_{issue}";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.Impl
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Atlassian.Jira;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Check.Response;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Create.Request;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Services.Interfaces;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
public class JiraClient : IJiraClient
|
||||||
|
{
|
||||||
|
private readonly ILogger<JiraClient> logger;
|
||||||
|
private readonly Jira jira;
|
||||||
|
|
||||||
|
public JiraClient(
|
||||||
|
ILogger<JiraClient> logger,
|
||||||
|
Jira jira)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.jira = jira;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CheckResponse> GetIssueStatus(string issueId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var issue = await this.jira.Issues.GetIssueAsync(issueId, cancellationToken).ConfigureAwait(false);
|
||||||
|
var result = new CheckResponse
|
||||||
|
{
|
||||||
|
Resolution = issue.Resolution?.Name,
|
||||||
|
Status = issue.Status.Name,
|
||||||
|
Success = true,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> CreateIssue(CreateJiraRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var issue = this.jira.CreateIssue(request.Project);
|
||||||
|
issue.Summary = $"[Bot] {request.Description[0..(Math.Min(50, request.Description.Length) - 1)]}...";
|
||||||
|
issue.Description = request.Description;
|
||||||
|
issue.Type = request.IssueType;
|
||||||
|
issue["Reporter name"] = request.Name;
|
||||||
|
issue["Reporter email"] = request.Email;
|
||||||
|
|
||||||
|
var result = await issue.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
if (request.Files?.Any() ?? false)
|
||||||
|
{
|
||||||
|
await issue.AddAttachmentAsync(
|
||||||
|
request.Files.Select(file => new UploadAttachmentInfo(file.Name, file.Content)).ToArray(),
|
||||||
|
cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.LogInformation("Created issue {issue} for request {request}", issue, request);
|
||||||
|
|
||||||
|
return result.Key.Value;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this.logger.LogError(ex, "Failed to create issue for requst {request}", request);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IReadOnlyList<ProjectDto>> GetProjects(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var projects = await this.jira.Projects.GetProjectsAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
var result = projects.Select(a => new ProjectDto
|
||||||
|
{
|
||||||
|
Key = a.Key,
|
||||||
|
Name = a.Name,
|
||||||
|
}).ToArray();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,139 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.Impl
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Check.Response;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Configuration;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Create.Request;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Create.Response;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Services.Interfaces;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
public class JiraService : IJiraService
|
||||||
|
{
|
||||||
|
private readonly HashSet<string> allowedProjects;
|
||||||
|
private readonly IJiraClient client;
|
||||||
|
private readonly ILogger<JiraService> logger;
|
||||||
|
private readonly IJiraCache cache;
|
||||||
|
|
||||||
|
public JiraService(
|
||||||
|
ILogger<JiraService> logger,
|
||||||
|
IJiraClient client,
|
||||||
|
IOptions<JiraConfig> options,
|
||||||
|
IJiraCache cache)
|
||||||
|
{
|
||||||
|
this.allowedProjects = new HashSet<string>(options.Value.AllowedProjects, StringComparer.OrdinalIgnoreCase);
|
||||||
|
this.client = client;
|
||||||
|
this.logger = logger;
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CreateResponse> CreateIssue(CreateJiraRequest request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!this.IsAllowedProject(request.Project))
|
||||||
|
{
|
||||||
|
this.logger.LogWarning("Tried to access disabled project {project} when creating issue {issue}", request.Project, request);
|
||||||
|
return new CreateResponse
|
||||||
|
{
|
||||||
|
IssueKey = null,
|
||||||
|
Message = "Invalid project",
|
||||||
|
Success = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await this.client.CreateIssue(request, cancellationToken).ConfigureAwait(false);
|
||||||
|
return new CreateResponse
|
||||||
|
{
|
||||||
|
Message = "Issue created!",
|
||||||
|
IssueKey = result,
|
||||||
|
Success = true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this.logger.LogError(ex, "Failed to create jira issue: {request}", request);
|
||||||
|
return new CreateResponse
|
||||||
|
{
|
||||||
|
IssueKey = null,
|
||||||
|
Message = "Failed to create an issue",
|
||||||
|
Success = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IReadOnlyList<ProjectDto>> GetProjects(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var cached = await this.cache.GetProjects().ConfigureAwait(false);
|
||||||
|
if (cached != null)
|
||||||
|
{
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await this.client.GetProjects(cancellationToken).ConfigureAwait(false);
|
||||||
|
result = result.Where(a => this.IsAllowedProject(a.Key)).ToList();
|
||||||
|
|
||||||
|
await this.cache.SetProjects(result).ConfigureAwait(false);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this.logger.LogError(ex, "Failed to get projects for the desk form");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CheckResponse> GetIssueStatus(string issue, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var project = issue.Split('-').First();
|
||||||
|
if (!this.IsAllowedProject(project))
|
||||||
|
{
|
||||||
|
this.logger.LogWarning("Tried to access disabled project {project} for issue {issue}", project, issue);
|
||||||
|
return new CheckResponse
|
||||||
|
{
|
||||||
|
Resolution = "No such issue",
|
||||||
|
Status = "Invalid project",
|
||||||
|
Success = false,
|
||||||
|
Issue = issue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckResponse result;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var cached = await this.cache.GetIssueStatus(issue).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var status = await this.client.GetIssueStatus(issue, cancellationToken).ConfigureAwait(false);
|
||||||
|
result = new CheckResponse
|
||||||
|
{
|
||||||
|
Resolution = status.Resolution,
|
||||||
|
Status = status.Status,
|
||||||
|
Success = true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this.logger.LogError(ex, "Failed to check status for issue {issue}", issue);
|
||||||
|
result = new CheckResponse
|
||||||
|
{
|
||||||
|
Resolution = null,
|
||||||
|
Status = null,
|
||||||
|
Success = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.cache.SetIssue(issue, result).ConfigureAwait(false);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsAllowedProject(string key) => this.allowedProjects.Contains(key);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.Impl
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
|
||||||
|
public abstract class JsonCache
|
||||||
|
{
|
||||||
|
private readonly IDistributedCache cache;
|
||||||
|
|
||||||
|
protected JsonCache(IDistributedCache cache)
|
||||||
|
{
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<T> GetCachedValue<T>(string key)
|
||||||
|
{
|
||||||
|
var cache = await this.cache.GetStringAsync(key).ConfigureAwait(false);
|
||||||
|
if (cache == null)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsonSerializer.Deserialize<T>(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Task SetCachedValue<T>(string key, T value, TimeSpan lifetime) =>
|
||||||
|
this.cache.SetStringAsync(
|
||||||
|
key,
|
||||||
|
JsonSerializer.Serialize<T>(value),
|
||||||
|
new DistributedCacheEntryOptions
|
||||||
|
{
|
||||||
|
SlidingExpiration = lifetime,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.Interfaces
|
||||||
|
{
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public interface ICaptchaValidator
|
||||||
|
{
|
||||||
|
Task<bool> Validate(string response, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.Interfaces
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Check.Response;
|
||||||
|
|
||||||
|
public interface IJiraCache
|
||||||
|
{
|
||||||
|
Task<IReadOnlyList<ProjectDto>> GetProjects();
|
||||||
|
|
||||||
|
Task SetProjects(IReadOnlyList<ProjectDto> value);
|
||||||
|
|
||||||
|
Task<CheckResponse> GetIssueStatus(string issue);
|
||||||
|
|
||||||
|
Task SetIssue(string issue, CheckResponse value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.Interfaces
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Check.Response;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Create.Request;
|
||||||
|
|
||||||
|
public interface IJiraClient
|
||||||
|
{
|
||||||
|
Task<CheckResponse> GetIssueStatus(string issueId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<string> CreateIssue(CreateJiraRequest request, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<IReadOnlyList<ProjectDto>> GetProjects(CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter.Services.Interfaces
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Check.Response;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Create.Request;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Create.Response;
|
||||||
|
|
||||||
|
public interface IJiraService
|
||||||
|
{
|
||||||
|
Task<CheckResponse> GetIssueStatus(string issue, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<IReadOnlyList<ProjectDto>> GetProjects(CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task<CreateResponse> CreateIssue(CreateJiraRequest request, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
86
src/epicmorg.jira.issue.web.reporter/Startup.cs
Normal file
86
src/epicmorg.jira.issue.web.reporter/Startup.cs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
namespace epicmorg.jira.issue.web.reporter
|
||||||
|
{
|
||||||
|
using epicmorg.jira.issue.web.reporter.Models.Configuration;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Services.DI;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Services.Impl;
|
||||||
|
using epicmorg.jira.issue.web.reporter.Services.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public Startup(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
this.Configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services
|
||||||
|
.AddControllersWithViews();
|
||||||
|
services
|
||||||
|
.AddMvc()
|
||||||
|
.AddMvcLocalization()
|
||||||
|
.AddDataAnnotationsLocalization();
|
||||||
|
|
||||||
|
services
|
||||||
|
.AddOptions()
|
||||||
|
.Configure<JiraConfig>(this.Configuration.GetSection("Jira"))
|
||||||
|
.Configure<UiConfig>(this.Configuration.GetSection("UI"))
|
||||||
|
.Configure<CaptchaConfig>(this.Configuration.GetSection("Captcha"));
|
||||||
|
|
||||||
|
services
|
||||||
|
.AddAntiforgery(o =>
|
||||||
|
{
|
||||||
|
o.SuppressXFrameOptionsHeader = true;
|
||||||
|
o.Cookie.SameSite = SameSiteMode.None;
|
||||||
|
})
|
||||||
|
.AddHttpClient()
|
||||||
|
.AddHttpClient<ICaptchaValidator, GoogleRecaptchaValidator>();
|
||||||
|
|
||||||
|
services
|
||||||
|
.AddJira()
|
||||||
|
//.AddScoped<IDistributedCache, MemoryDistributedCache>()
|
||||||
|
.AddScoped<IJiraCache, Services.Impl.JiraCache>()
|
||||||
|
.AddScoped<IJiraClient, JiraClient>()
|
||||||
|
.AddScoped<IJiraService, JiraService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
|
{
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseDeveloperExceptionPage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
app.UseExceptionHandler("/Home/Error");
|
||||||
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||||
|
app.UseHsts();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
app.UseStaticFiles();
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapControllerRoute(
|
||||||
|
name: "default",
|
||||||
|
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
src/epicmorg.jira.issue.web.reporter/Views/Home/Check.cshtml
Normal file
30
src/epicmorg.jira.issue.web.reporter/Views/Home/Check.cshtml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
@inject IOptions<CaptchaConfig> captchaConfig
|
||||||
|
@model CheckRequest
|
||||||
|
<form asp-action="Check" id="form" asp-all-route-data="new Dictionary<string, string>()">
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||||
|
<label asp-for="Issue"><i class="fas fa-keyboard"></i> <span data-localize="label-enter-issue-key">Enter issue key</span>:</label>
|
||||||
|
<input type="text" asp-for="Issue" class="form-control" placeholder="ABC-123" value="" required>
|
||||||
|
<span asp-validation-for="Issue" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="g-recaptcha" data-sitekey="@captchaConfig.Value.Key" data-callback="recaptchaCallback"></div>
|
||||||
|
</div>
|
||||||
|
<span asp-validation-for="Captcha" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<button class="btn btn-primary btn-lg btn-block" type="submit"><span data-localize="label-check">Check</span> <i class="fas fa-hand-pointer"></i></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@section Head {
|
||||||
|
<script src='https://www.google.com/recaptcha/api.js'></script>
|
||||||
|
}
|
||||||
|
@section Scripts{
|
||||||
|
@{await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
@model CheckResponse
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="disabled-ui-text"><i class="fas fa-keyboard"></i> <span data-localize="label-issue-key">Issue key</span>:</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@if (!Model.Success) {
|
||||||
|
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||||
|
<strong><i class="fas fa-exclamation-triangle"></i> <span data-localize="message-error">Error!</span></strong> <span data-localize="message-something-wrong-2">Something went wrong. Failed to create request.</span> @Model.Message
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
} else {
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header"><input asp-for="Issue" id="disabled-ui-text" class="form-control" readonly></h5>
|
||||||
|
<div class="card-body">
|
||||||
|
@if (Model.Status != null) {
|
||||||
|
<p class="card-text"><span data-localize="message-status">Status</span>: <span class="badge badge-info">@Model.Status</span></p>
|
||||||
|
|
||||||
|
}
|
||||||
|
@if (Model.Resolution != null) {
|
||||||
|
<p class="card-text"><span data-localize="message-resolution">Resolution</span>: <span class="text-muted">@Model.Resolution</span></p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 padding-fix">
|
||||||
|
<a class="btn btn-primary btn-lg btn-block" asp-action="Create">
|
||||||
|
<i class="fas fa-bug"></i> <span data-localize="label-submit-another">Submit Another Issue</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 padding-fix">
|
||||||
|
<a class="btn btn-primary btn-lg btn-block" asp-action="Check">
|
||||||
|
<i class="fas fa-search"></i> <span data-localize="label-check-another">Check Another Report</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,98 @@
|
|||||||
|
@inject IOptions<CaptchaConfig> captchaConfig
|
||||||
|
@inject IOptions<UiConfig> uiConfig
|
||||||
|
@model CreateViewModel
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12 order-md-1">
|
||||||
|
<form asp-action="Create" enctype="multipart/form-data" id="form">
|
||||||
|
<div asp-validation-summary="ModelOnly" class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||||
|
<strong><i class="fas fa-exclamation-triangle"></i> <span data-localize="message-error">Error!</span></strong> <span data-localize="message-something-wrong">Something went wrong.</span>
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Name" class="control-label"><i class="fas fa-user"></i> <span data-localize="label-fn">First name</span>:</label>
|
||||||
|
<input asp-for="Name" type="text" class="form-control" id="firstName" placeholder="" value="" required>
|
||||||
|
<span asp-validation-for="Name" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Email" class="control-label"><i class="far fa-envelope"></i> Email:</label>
|
||||||
|
<input asp-for="Email" type="email" class="form-control" id="email" placeholder="you@example.com">
|
||||||
|
<span asp-validation-for="Email" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
@if (Model.IssueTypes?.Count() > 1)
|
||||||
|
{
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="IssueType" class="control-label"><i class="fas fa-list"></i> <span data-localize="label-rep-type">Report type</span>:</label>
|
||||||
|
<select asp-for="IssueType" asp-items="@Model.IssueTypes" class="form-control custom-select d-block w-100" required>
|
||||||
|
<option disabled selected data-localize="label-select">--- SELECT ---</option>
|
||||||
|
</select>
|
||||||
|
<span asp-validation-for="IssueType" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="hidden" asp-for="IssueType" value="@Model.IssueTypes.FirstOrDefault()?.Value" />
|
||||||
|
}
|
||||||
|
@if (Model.Projects?.Count() > 1)
|
||||||
|
{
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Project" class="control-label"><i class="fas fa-list"></i> <span data-localize="label-project">Select project</span>:</label>
|
||||||
|
<select class="custom-select d-block w-100 form-control" asp-for="Project" asp-items="@Model.Projects" required>
|
||||||
|
<option disabled selected data-localize="label-select">--- SELECT ---</option>
|
||||||
|
</select>
|
||||||
|
<span asp-validation-for="Project" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="hidden" asp-for="Project" value="@Model.Projects.FirstOrDefault()?.Value" />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Description" class="control-label"><i class="fas fa-keyboard"></i> <span data-localize="label-description">Your description</span>:</label>
|
||||||
|
<textarea asp-for="Description" class="form-control" rows="3"></textarea>
|
||||||
|
<span asp-validation-for="Description" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Files" class="control-label"><i class="fas fa-file-upload"></i> <span data-localize="label-attach-file">Attach file</span>:</label>
|
||||||
|
<input asp-for="Files" typeclass="form-control" multiple type="file" class="form-control-file">
|
||||||
|
<span asp-validation-for="Files" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-md-6 mb-3">
|
||||||
|
<div class="g-recaptcha" data-sitekey="@captchaConfig.Value.Key"></div>
|
||||||
|
<span asp-validation-for="Captcha" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary btn-lg btn-block" type="submit"><span data-localize="label-submit">Submit report</span> <i class="fas fa-paper-plane"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@section Head {
|
||||||
|
<script src='https://www.google.com/recaptcha/api.js'></script>
|
||||||
|
}
|
||||||
|
@section Scripts{
|
||||||
|
@{await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
@model CreateResponse
|
||||||
|
|
||||||
|
@if (Model.Success)
|
||||||
|
{
|
||||||
|
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||||
|
<strong>
|
||||||
|
<i class="fas fa-hands-helping"></i> <span data-localize="message-awesome">Awesome!</span>
|
||||||
|
</strong>
|
||||||
|
<span data-localize="message-reported-ok">You successfully send your report. Your issue-key is</span>:
|
||||||
|
<strong>
|
||||||
|
<a asp-action="Check" asp-route-id="@Model.IssueKey">@Model.IssueKey</a>
|
||||||
|
</strong>.
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||||
|
<strong><i class="fas fa-exclamation-triangle"></i> <span data-localize="message-error">Error!</span></strong> <span data-localize="message-something-wrong">Something went wrong.</span> @Model.Message
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 padding-fix">
|
||||||
|
<a class="btn btn-primary btn-lg btn-block" asp-action="Create">
|
||||||
|
<i class="fas fa-bug"></i> <span data-localize="label-submit-another">Submit Another Issue</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 padding-fix">
|
||||||
|
<a class="btn btn-primary btn-lg btn-block" asp-action="Check">
|
||||||
|
<i class="fas fa-search"></i> <span data-localize="label-check-another">Check Another Report</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
22
src/epicmorg.jira.issue.web.reporter/Views/Home/Index.cshtml
Normal file
22
src/epicmorg.jira.issue.web.reporter/Views/Home/Index.cshtml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@inject IOptions<UiConfig> uiConfig
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 padding-fix">
|
||||||
|
<div class="card border-secondary ">
|
||||||
|
<div class="card-body">
|
||||||
|
<a class="btn btn-link btn-lg btn-block text-muted" asp-action="Create">
|
||||||
|
<i class="fas fa-bug"></i> <span data-localize="btn-submit-new-issue">Submit New Issue</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 padding-fix">
|
||||||
|
<div class="card border-secondary ">
|
||||||
|
<div class="card-body">
|
||||||
|
<a class="btn btn-link btn-lg btn-block text-muted" asp-action="Check">
|
||||||
|
<i class="fas fa-search"></i> <span data-localize="btn-check-report">Check Report</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,2 @@
|
|||||||
|
<h3>3rd party licenses:</h3>
|
||||||
|
<div>Icons made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a></div>
|
@ -0,0 +1,25 @@
|
|||||||
|
@model ErrorViewModel
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Error";
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1 class="text-danger">Error.</h1>
|
||||||
|
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||||
|
|
||||||
|
@if (Model.ShowRequestId)
|
||||||
|
{
|
||||||
|
<p>
|
||||||
|
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
<h3>Development Mode</h3>
|
||||||
|
<p>
|
||||||
|
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||||
|
It can result in displaying sensitive information from exceptions to end users.
|
||||||
|
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||||
|
and restarting the app.
|
||||||
|
</p>
|
@ -0,0 +1,90 @@
|
|||||||
|
@using System.Reflection
|
||||||
|
@inject IOptions<UiConfig> uiConfig
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<title>@uiConfig.Value.HeaderText - @uiConfig.Value.GetAssemblyProduct</title>
|
||||||
|
<link href="~/lib/fontawesome/5.11.2-web/css/all.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="~/lib/bootstrap/themes/@uiConfig.Value.Theme/bootstrap.min.css" />
|
||||||
|
<link rel="stylesheet" href="~/css/site.css" />
|
||||||
|
@RenderSection("Head", required: false)
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<main role="main" class="pb-3">
|
||||||
|
<div class="py-3 text-center">
|
||||||
|
<a asp-action="Index">
|
||||||
|
<img class="d-block mx-auto mb-4" src="@uiConfig.Value.LogoUrl" alt="@uiConfig.Value.HeaderText - @uiConfig.Value.DescriptionText" title="@uiConfig.Value.HeaderText - @uiConfig.Value.DescriptionText" width="72" height="72">
|
||||||
|
</a>
|
||||||
|
<h2>@uiConfig.Value.HeaderText</h2>
|
||||||
|
<p class="lead">@uiConfig.Value.DescriptionText</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@RenderBody()
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer text-muted text-center">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm">
|
||||||
|
<p class="mb-1">
|
||||||
|
<i class="far fa-copyright"></i> 2009-@DateTime.Now.Year.ToString() EpicMorg
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<p class="mb-1">
|
||||||
|
<i class="fas fa-cubes"></i> @uiConfig.Value.GetAssemblyProduct: <a class="text-secondary" href="https://github.com/EpicMorg/jira-issue-web-reporter/releases" target="_blank">@uiConfig.Value.GetAssemblyVersion()</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<p class="mb-1">
|
||||||
|
<i class="fas fa-key"></i> <span data-localize="label-licensed-to">Liceensed to</span>: @uiConfig.Value.LicensedTo
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="list-inline">
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<a asp-action="Create">
|
||||||
|
<i class="fas fa-bug"></i> <span data-localize="btn-submit-new-issue">Submit New Issue</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<a asp-action="Check">
|
||||||
|
<i class="fas fa-search"></i> <span data-localize="btn-check-report">Check Report</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<div class="dropdown dropup">
|
||||||
|
<a class="dropdown-toggle" href="#" role="button" id="" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<i class="fas fa-language"></i> <span data-localize="lang-language">Language</span>
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
|
||||||
|
<a class="dropdown-item" href="#" id="lang_en_btn">
|
||||||
|
<img height="16" src="~/lib/flags/png/260-united-kingdom.png" alt="" class="mr-2">
|
||||||
|
<span data-localize="lang-english">English</span>
|
||||||
|
</a>
|
||||||
|
<a class="dropdown-item" href="#" id="lang_ru_btn">
|
||||||
|
<img height="16" src="~/lib/flags/png/248-russia.png" alt="" class="mr-2">
|
||||||
|
<span data-localize="lang-rusian">Russian</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||||
|
<script src="~/lib/jquery-localize/jquery.localize.min.js"></script>
|
||||||
|
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||||
|
@RenderSection("Scripts", required: false)
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,18 @@
|
|||||||
|
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
|
||||||
|
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
|
||||||
|
<script>
|
||||||
|
window.onload = function () {
|
||||||
|
jQuery.validator.addMethod('checkCaptcha', function (value, element) {
|
||||||
|
//https://stackoverflow.com/a/34746663
|
||||||
|
return grecaptcha.getResponse() !== '';
|
||||||
|
}, 'Invalid captcha');
|
||||||
|
|
||||||
|
jQuery.validator.addClassRules({
|
||||||
|
'g-recaptcha-response': {
|
||||||
|
checkCaptcha: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#form').validate();
|
||||||
|
};
|
||||||
|
</script>
|
@ -0,0 +1,10 @@
|
|||||||
|
@using epicmorg.jira.issue.web.reporter
|
||||||
|
@using epicmorg.jira.issue.web.reporter.Models
|
||||||
|
@using epicmorg.jira.issue.web.reporter.Models.Create.ViewModels
|
||||||
|
@using epicmorg.jira.issue.web.reporter.Models.Check.Request
|
||||||
|
@using epicmorg.jira.issue.web.reporter.Models.Create.Response
|
||||||
|
@using epicmorg.jira.issue.web.reporter.Models.Check.Response
|
||||||
|
@using Microsoft.Extensions.Options
|
||||||
|
@using epicmorg.jira.issue.web.reporter.Models.Configuration
|
||||||
|
|
||||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
@ -0,0 +1,3 @@
|
|||||||
|
@{
|
||||||
|
Layout = "_Layout";
|
||||||
|
}
|
9
src/epicmorg.jira.issue.web.reporter/appsettings.json
Normal file
9
src/epicmorg.jira.issue.web.reporter/appsettings.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<UserSecretsId>988e0611-42e5-4c51-9300-0b75e780c73a</UserSecretsId>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<PackageId>epicmorg.jira.issue.web.reporter</PackageId>
|
||||||
|
<Version>1.0.0.17</Version>
|
||||||
|
<Authors>epicm.org</Authors>
|
||||||
|
<Product>Jira issue web reporter</Product>
|
||||||
|
<Copyright>EpicM.org</Copyright>
|
||||||
|
<Description>Web-based simple issue reporter via official rest-api.</Description>
|
||||||
|
<AssemblyName>epicmorg.jira.issue.web.reporter</AssemblyName>
|
||||||
|
<RootNamespace>epicmorg.jira.issue.web.reporter</RootNamespace>
|
||||||
|
<ApplicationIcon>wwwroot\favicon.ico</ApplicationIcon>
|
||||||
|
<PackageProjectUrl>https://ww.epicm.org/</PackageProjectUrl>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
|
||||||
|
<PackageReference Include="Automapper" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Atlassian.SDK" Version="11.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.5" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
84
src/epicmorg.jira.issue.web.reporter/wwwroot/css/site.css
Normal file
84
src/epicmorg.jira.issue.web.reporter/wwwroot/css/site.css
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
|
||||||
|
a.navbar-brand {
|
||||||
|
white-space: normal;
|
||||||
|
text-align: center;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sticky footer styles
|
||||||
|
-------------------------------------------------- */
|
||||||
|
html {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
html {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-shadow {
|
||||||
|
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
|
||||||
|
}
|
||||||
|
|
||||||
|
button.accept-policy {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sticky footer styles
|
||||||
|
-------------------------------------------------- */
|
||||||
|
html {
|
||||||
|
position: relative;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
/* Margin bottom by footer height */
|
||||||
|
margin-bottom: 60px;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
/* line-height: 60px; Vertically center the text there */
|
||||||
|
}
|
||||||
|
|
||||||
|
#g-recaptcha-response {
|
||||||
|
display: block !important;
|
||||||
|
position: absolute;
|
||||||
|
margin: -78px 0 0 0 !important;
|
||||||
|
width: 302px !important;
|
||||||
|
height: 76px !important;
|
||||||
|
z-index: -999999;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.padding-fix {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, .btn-link {
|
||||||
|
outline: none !important;
|
||||||
|
outline-style: none !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 960px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-placeholder-img {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
text-anchor: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bd-placeholder-img-lg {
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lh-condensed {
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
BIN
src/epicmorg.jira.issue.web.reporter/wwwroot/favicon.ico
Normal file
BIN
src/epicmorg.jira.issue.web.reporter/wwwroot/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 109 KiB |
53
src/epicmorg.jira.issue.web.reporter/wwwroot/js/site.js
Normal file
53
src/epicmorg.jira.issue.web.reporter/wwwroot/js/site.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
$(document).ready(function () {
|
||||||
|
console.log("crap.js v1.1 inintialized");
|
||||||
|
|
||||||
|
var userLang = navigator.language || navigator.userLanguage;
|
||||||
|
|
||||||
|
if (localStorage.getItem("selectedLang") === null) {
|
||||||
|
console.log('selectedLang is empty');
|
||||||
|
localStorage.setItem('selectedLang', userLang);
|
||||||
|
console.log(`selectedLang now is ${localStorage.selectedLang}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
$.setRussianLang = function () {
|
||||||
|
$("#lang_en_btn").removeClass("active");
|
||||||
|
$("#lang_ru_btn").addClass("active");
|
||||||
|
$("[data-localize]").localize("site", { language: "ru", pathPrefix: "/lib/jquery-localize/lang/" });
|
||||||
|
};
|
||||||
|
|
||||||
|
$.setEnglishLang = function () {
|
||||||
|
$("#lang_ru_btn").removeClass("active");
|
||||||
|
$("#lang_en_btn").addClass("active");
|
||||||
|
$("[data-localize]").localize("site", { language: "en", pathPrefix: "/lib/jquery-localize/lang/" });
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (localStorage.selectedLang) {
|
||||||
|
case "ru-RU":
|
||||||
|
$.setRussianLang();
|
||||||
|
break;
|
||||||
|
// case "en-US":
|
||||||
|
// $.setEnglishLang();
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
$.setEnglishLang();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$("#lang_ru_btn").click(function (e) {
|
||||||
|
console.log("lang_ru_btn");
|
||||||
|
userLang = "ru-RU";
|
||||||
|
localStorage.setItem('selectedLang', userLang);
|
||||||
|
console.log(`selectedLang is ${localStorage.selectedLang}`);
|
||||||
|
$.setRussianLang();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#lang_en_btn").click(function (e) {
|
||||||
|
console.log("lang_en_btn");
|
||||||
|
userLang = "en-US";
|
||||||
|
localStorage.setItem('selectedLang', userLang);
|
||||||
|
console.log(`selectedLang is ${localStorage.selectedLang}`);
|
||||||
|
$.setEnglishLang();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2011-2018 Twitter, Inc.
|
||||||
|
Copyright (c) 2011-2018 The Bootstrap Authors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
3719
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css
vendored
Normal file
3719
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map
vendored
Normal file
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css
vendored
Normal file
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
331
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css
vendored
Normal file
331
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css
vendored
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2019 The Bootstrap Authors
|
||||||
|
* Copyright 2011-2019 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||||
|
*/
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: sans-serif;
|
||||||
|
line-height: 1.15;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #212529;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
[tabindex="-1"]:focus {
|
||||||
|
outline: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
box-sizing: content-box;
|
||||||
|
height: 0;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr[title],
|
||||||
|
abbr[data-original-title] {
|
||||||
|
text-decoration: underline;
|
||||||
|
-webkit-text-decoration: underline dotted;
|
||||||
|
text-decoration: underline dotted;
|
||||||
|
cursor: help;
|
||||||
|
border-bottom: 0;
|
||||||
|
-webkit-text-decoration-skip-ink: none;
|
||||||
|
text-decoration-skip-ink: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
address {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-style: normal;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol,
|
||||||
|
ul,
|
||||||
|
dl {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol ol,
|
||||||
|
ul ul,
|
||||||
|
ol ul,
|
||||||
|
ul ol {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
position: relative;
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #007bff;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #0056b3;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:not([href]):not([tabindex]) {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:not([href]):not([tabindex]):focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre,
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
vertical-align: middle;
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
caption {
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
padding-bottom: 0.75rem;
|
||||||
|
color: #6c757d;
|
||||||
|
text-align: left;
|
||||||
|
caption-side: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus {
|
||||||
|
outline: 1px dotted;
|
||||||
|
outline: 5px auto -webkit-focus-ring-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
button,
|
||||||
|
select,
|
||||||
|
optgroup,
|
||||||
|
textarea {
|
||||||
|
margin: 0;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type="button"],
|
||||||
|
[type="reset"],
|
||||||
|
[type="submit"] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:disabled),
|
||||||
|
[type="button"]:not(:disabled),
|
||||||
|
[type="reset"]:not(:disabled),
|
||||||
|
[type="submit"]:not(:disabled) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
[type="button"]::-moz-focus-inner,
|
||||||
|
[type="reset"]::-moz-focus-inner,
|
||||||
|
[type="submit"]::-moz-focus-inner {
|
||||||
|
padding: 0;
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="radio"],
|
||||||
|
input[type="checkbox"] {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="date"],
|
||||||
|
input[type="time"],
|
||||||
|
input[type="datetime-local"],
|
||||||
|
input[type="month"] {
|
||||||
|
-webkit-appearance: listbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
min-width: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type="number"]::-webkit-inner-spin-button,
|
||||||
|
[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type="search"] {
|
||||||
|
outline-offset: -2px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
font: inherit;
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
output {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map
vendored
Normal file
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
8
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css
vendored
Normal file
8
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2019 The Bootstrap Authors
|
||||||
|
* Copyright 2011-2019 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||||
|
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||||
|
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
File diff suppressed because one or more lines are too long
10038
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap.css
vendored
Normal file
10038
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map
vendored
Normal file
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css
vendored
Normal file
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map
vendored
Normal file
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7013
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js
vendored
Normal file
7013
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map
vendored
Normal file
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js
vendored
Normal file
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4435
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.js
vendored
Normal file
4435
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map
vendored
Normal file
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js
vendored
Normal file
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map
vendored
Normal file
1
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,103 @@
|
|||||||
|
// Cerulean 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
|
||||||
|
@mixin btn-shadow($color){
|
||||||
|
@include gradient-y-three-colors(lighten($color, 8%), $color, 60%, darken($color, 4%));
|
||||||
|
}
|
||||||
|
|
||||||
|
$text-shadow: 0 1px 0 rgba(0, 0, 0, 0.05) !default;
|
||||||
|
|
||||||
|
// Navbar ======================================================================
|
||||||
|
|
||||||
|
.bg-primary {
|
||||||
|
@include btn-shadow($primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-dark {
|
||||||
|
@include btn-shadow($blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-light {
|
||||||
|
@include gradient-y-three-colors(lighten($gray-200, 8%), $gray-200, 60%, darken($gray-200, 2%));
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand,
|
||||||
|
.nav-link {
|
||||||
|
text-shadow: $text-shadow
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons =====================================================================
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
text-shadow: $text-shadow
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
@include btn-shadow($primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
@include btn-shadow($secondary);
|
||||||
|
color: $gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-success {
|
||||||
|
@include btn-shadow($success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-info {
|
||||||
|
@include btn-shadow($info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-warning {
|
||||||
|
@include btn-shadow($warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger {
|
||||||
|
@include btn-shadow($danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-light {
|
||||||
|
@include btn-shadow($light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-dark {
|
||||||
|
@include btn-shadow($dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Typography ==================================================================
|
||||||
|
|
||||||
|
.text-secondary {
|
||||||
|
color: $gray-500 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-primary,
|
||||||
|
.bg-success,
|
||||||
|
.bg-info,
|
||||||
|
.bg-warning,
|
||||||
|
.bg-danger,
|
||||||
|
.bg-dark {
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tables ======================================================================
|
||||||
|
|
||||||
|
// Forms =======================================================================
|
||||||
|
|
||||||
|
// Navs ========================================================================
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
.dropdown-header {
|
||||||
|
color: $gray-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicators ==================================================================
|
||||||
|
|
||||||
|
// Progress bars ===============================================================
|
||||||
|
|
||||||
|
// Containers ==================================================================
|
@ -0,0 +1,57 @@
|
|||||||
|
// Cerulean 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
//
|
||||||
|
// Color system
|
||||||
|
//
|
||||||
|
|
||||||
|
$white: #fff !default;
|
||||||
|
$gray-100: #f8f9fa !default;
|
||||||
|
$gray-200: #e9ecef !default;
|
||||||
|
$gray-300: #dee2e6 !default;
|
||||||
|
$gray-400: #ced4da !default;
|
||||||
|
$gray-500: #adb5bd !default;
|
||||||
|
$gray-600: #868e96 !default;
|
||||||
|
$gray-700: #495057 !default;
|
||||||
|
$gray-800: #343a40 !default;
|
||||||
|
$gray-900: #212529 !default;
|
||||||
|
$black: #000 !default;
|
||||||
|
|
||||||
|
$blue: #033C73 !default;
|
||||||
|
$indigo: #6610f2 !default;
|
||||||
|
$purple: #6f42c1 !default;
|
||||||
|
$pink: #e83e8c !default;
|
||||||
|
$red: #C71C22 !default;
|
||||||
|
$orange: #fd7e14 !default;
|
||||||
|
$yellow: #DD5600 !default;
|
||||||
|
$green: #73A839 !default;
|
||||||
|
$teal: #20c997 !default;
|
||||||
|
$cyan: #2FA4E7 !default;
|
||||||
|
|
||||||
|
$primary: $cyan !default;
|
||||||
|
$secondary: $gray-200 !default;
|
||||||
|
$success: $green !default;
|
||||||
|
$info: $blue !default;
|
||||||
|
$warning: $yellow !default;
|
||||||
|
$danger: $red !default;
|
||||||
|
$light: $gray-100 !default;
|
||||||
|
$dark: $gray-800 !default;
|
||||||
|
|
||||||
|
// Body
|
||||||
|
|
||||||
|
$body-color: $gray-700 !default;
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
|
||||||
|
$headings-color: $cyan !default;
|
||||||
|
|
||||||
|
// Dropdowns
|
||||||
|
|
||||||
|
$dropdown-link-color: $body-color !default;
|
||||||
|
$dropdown-link-hover-color: $white !default;
|
||||||
|
$dropdown-link-hover-bg: $primary !default;
|
||||||
|
|
||||||
|
// Navbar
|
||||||
|
|
||||||
|
$navbar-dark-color: rgba($white,.8) !default;
|
||||||
|
$navbar-dark-hover-color: $white !default;
|
10872
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cerulean/bootstrap.css
vendored
Normal file
10872
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cerulean/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cerulean/bootstrap.min.css
vendored
Normal file
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cerulean/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,38 @@
|
|||||||
|
// Cosmo 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
|
||||||
|
// Variables ===================================================================
|
||||||
|
|
||||||
|
$web-font-path: "https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700" !default;
|
||||||
|
@import url($web-font-path);
|
||||||
|
|
||||||
|
// Navbar ======================================================================
|
||||||
|
|
||||||
|
// Buttons =====================================================================
|
||||||
|
|
||||||
|
// Typography ==================================================================
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tables ======================================================================
|
||||||
|
|
||||||
|
// Forms =======================================================================
|
||||||
|
|
||||||
|
// Navs ========================================================================
|
||||||
|
|
||||||
|
// Indicators ==================================================================
|
||||||
|
|
||||||
|
// Progress bars ===============================================================
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
@include box-shadow(none);
|
||||||
|
.progress-bar {
|
||||||
|
font-size: 8px;
|
||||||
|
line-height: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Containers ==================================================================
|
@ -0,0 +1,68 @@
|
|||||||
|
// Cosmo 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
//
|
||||||
|
// Color system
|
||||||
|
//
|
||||||
|
|
||||||
|
$white: #fff !default;
|
||||||
|
$gray-100: #f8f9fa !default;
|
||||||
|
$gray-200: #e9ecef !default;
|
||||||
|
$gray-300: #dee2e6 !default;
|
||||||
|
$gray-400: #ced4da !default;
|
||||||
|
$gray-500: #adb5bd !default;
|
||||||
|
$gray-600: #868e96 !default;
|
||||||
|
$gray-700: #495057 !default;
|
||||||
|
$gray-800: #373a3c !default;
|
||||||
|
$gray-900: #212529 !default;
|
||||||
|
$black: #000 !default;
|
||||||
|
|
||||||
|
$blue: #2780E3 !default;
|
||||||
|
$indigo: #6610f2 !default;
|
||||||
|
$purple: #613d7c !default;
|
||||||
|
$pink: #e83e8c !default;
|
||||||
|
$red: #FF0039 !default;
|
||||||
|
$orange: #f0ad4e !default;
|
||||||
|
$yellow: #FF7518 !default;
|
||||||
|
$green: #3FB618 !default;
|
||||||
|
$teal: #20c997 !default;
|
||||||
|
$cyan: #9954BB !default;
|
||||||
|
|
||||||
|
$primary: $blue !default;
|
||||||
|
$secondary: $gray-800 !default;
|
||||||
|
$success: $green !default;
|
||||||
|
$info: $cyan !default;
|
||||||
|
$warning: $yellow !default;
|
||||||
|
$danger: $red !default;
|
||||||
|
$light: $gray-100 !default;
|
||||||
|
$dark: $gray-800 !default;
|
||||||
|
|
||||||
|
// Options
|
||||||
|
|
||||||
|
$enable-rounded: false !default;
|
||||||
|
|
||||||
|
// Body
|
||||||
|
|
||||||
|
$body-color: $gray-800 !default;
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
|
||||||
|
$font-family-sans-serif: "Segoe UI", "Source Sans Pro", Calibri, Candara, Arial, sans-serif !default;
|
||||||
|
|
||||||
|
$font-size-base: 0.9375rem !default;
|
||||||
|
|
||||||
|
$headings-font-weight: 300 !default;
|
||||||
|
|
||||||
|
// Navbar
|
||||||
|
|
||||||
|
$navbar-dark-hover-color: rgba($white,1) !default;
|
||||||
|
|
||||||
|
$navbar-light-hover-color: rgba($black,.9) !default;
|
||||||
|
|
||||||
|
// Alerts
|
||||||
|
|
||||||
|
$alert-border-width: 0 !default;
|
||||||
|
|
||||||
|
// Progress bars
|
||||||
|
|
||||||
|
$progress-height: 0.5rem !default;
|
10502
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cosmo/bootstrap.css
vendored
Normal file
10502
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cosmo/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cosmo/bootstrap.min.css
vendored
Normal file
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cosmo/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,286 @@
|
|||||||
|
// Cyborg 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
|
||||||
|
// Variables ===================================================================
|
||||||
|
|
||||||
|
$web-font-path: "https://fonts.googleapis.com/css?family=Roboto:400,700" !default;
|
||||||
|
@import url($web-font-path);
|
||||||
|
|
||||||
|
// Navbar ======================================================================
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
|
||||||
|
&.bg-primary {
|
||||||
|
border: 1px solid $gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bg-dark {
|
||||||
|
background-color: $body-bg !important;
|
||||||
|
border: 1px solid $gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bg-light {
|
||||||
|
background-color: $gray-500 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fixed-top {
|
||||||
|
border-width: 0 0 1px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fixed-bottom {
|
||||||
|
border-width: 1px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons =====================================================================
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
@each $color, $value in $theme-colors {
|
||||||
|
&-#{$color} {
|
||||||
|
@if $enable-gradients {
|
||||||
|
background: $value linear-gradient(180deg, mix($white, $value, 15%), $value) repeat-x;
|
||||||
|
} @else {
|
||||||
|
background-color: $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typography ==================================================================
|
||||||
|
|
||||||
|
// Tables ======================================================================
|
||||||
|
|
||||||
|
table {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
|
||||||
|
&-primary {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-secondary {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-light {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-dark {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-success {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-info {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-danger {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-warning {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-active {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $table-active-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-hover {
|
||||||
|
|
||||||
|
.table-primary:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($primary, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-secondary:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($secondary, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-light:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($light, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-dark:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($dark, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-success:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($success, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-info:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($info, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-danger:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($danger, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-warning:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($warning, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-active:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $table-active-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forms =======================================================================
|
||||||
|
|
||||||
|
legend {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navs ========================================================================
|
||||||
|
|
||||||
|
.nav-tabs,
|
||||||
|
.nav-pills {
|
||||||
|
.nav-link {
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled,
|
||||||
|
&.disabled:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
color: $nav-link-disabled-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb {
|
||||||
|
a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicators ==================================================================
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
border: none;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
a,
|
||||||
|
.alert-link {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $color, $value in $theme-colors {
|
||||||
|
&-#{$color} {
|
||||||
|
@if $enable-gradients {
|
||||||
|
background: $value linear-gradient(180deg, mix($white, $value, 15%), $value) repeat-x;
|
||||||
|
} @else {
|
||||||
|
background-color: $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
&-warning {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
opacity: 0.6;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Progress bars ===============================================================
|
||||||
|
|
||||||
|
// Containers ==================================================================
|
||||||
|
|
||||||
|
.list-group-item {
|
||||||
|
&:hover {
|
||||||
|
background-color: $gray-700;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-action {
|
||||||
|
color: $gray-500;
|
||||||
|
|
||||||
|
.list-group-item-heading {
|
||||||
|
color: $gray-500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .list-group-item-heading {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card,
|
||||||
|
.list-group-item {
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.popover {
|
||||||
|
&-title {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,173 @@
|
|||||||
|
// Cyborg 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
//
|
||||||
|
// Color system
|
||||||
|
//
|
||||||
|
|
||||||
|
$white: #fff !default;
|
||||||
|
$gray-100: #f8f9fa !default;
|
||||||
|
$gray-200: #e9ecef !default;
|
||||||
|
$gray-300: #dee2e6 !default;
|
||||||
|
$gray-400: #ADAFAE !default;
|
||||||
|
$gray-500: #888 !default;
|
||||||
|
$gray-600: #555 !default;
|
||||||
|
$gray-700: #282828 !default;
|
||||||
|
$gray-800: #222 !default;
|
||||||
|
$gray-900: #212529 !default;
|
||||||
|
$black: #000 !default;
|
||||||
|
|
||||||
|
$blue: #2A9FD6 !default;
|
||||||
|
$indigo: #6610f2 !default;
|
||||||
|
$purple: #6f42c1 !default;
|
||||||
|
$pink: #e83e8c !default;
|
||||||
|
$red: #CC0000 !default;
|
||||||
|
$orange: #fd7e14 !default;
|
||||||
|
$yellow: #FF8800 !default;
|
||||||
|
$green: #77B300 !default;
|
||||||
|
$teal: #20c997 !default;
|
||||||
|
$cyan: #9933CC !default;
|
||||||
|
|
||||||
|
$primary: $blue !default;
|
||||||
|
$secondary: $gray-600 !default;
|
||||||
|
$success: $green !default;
|
||||||
|
$info: $cyan !default;
|
||||||
|
$warning: $yellow !default;
|
||||||
|
$danger: $red !default;
|
||||||
|
$light: $gray-800 !default;
|
||||||
|
$dark: $gray-400 !default;
|
||||||
|
|
||||||
|
$yiq-contrasted-threshold: 175 !default;
|
||||||
|
|
||||||
|
|
||||||
|
// Body
|
||||||
|
|
||||||
|
$body-bg: #060606 !default;
|
||||||
|
$body-color: $gray-400 !default;
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
|
||||||
|
$font-family-sans-serif: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !default;
|
||||||
|
|
||||||
|
$font-size-base: .875rem !default;
|
||||||
|
|
||||||
|
$h1-font-size: 4rem !default;
|
||||||
|
$h2-font-size: 3rem !default;
|
||||||
|
$h3-font-size: 2.5rem !default;
|
||||||
|
$h4-font-size: 2rem !default;
|
||||||
|
$h5-font-size: 1.5rem !default;
|
||||||
|
|
||||||
|
$headings-color: $white !default;
|
||||||
|
|
||||||
|
// Tables
|
||||||
|
|
||||||
|
$table-color: $white !default;
|
||||||
|
$table-accent-bg: rgba($white,.05) !default;
|
||||||
|
$table-hover-bg: rgba($white,.075) !default;
|
||||||
|
|
||||||
|
$table-border-color: $gray-700 !default;
|
||||||
|
|
||||||
|
$table-dark-bg: $gray-500 !default;
|
||||||
|
$table-dark-border-color: darken($gray-500, 7.5%) !default;
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
|
||||||
|
$input-btn-padding-x: 1rem !default;
|
||||||
|
|
||||||
|
// Forms
|
||||||
|
|
||||||
|
$input-disabled-bg: $gray-400 !default;
|
||||||
|
|
||||||
|
$input-border-color: transparent !default;
|
||||||
|
|
||||||
|
$input-group-addon-color: $white !default;
|
||||||
|
$input-group-addon-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
$custom-file-color: $white !default;
|
||||||
|
$custom-file-border-color: $gray-700 !default;
|
||||||
|
|
||||||
|
// Dropdowns
|
||||||
|
|
||||||
|
$dropdown-bg: $gray-700 !default;
|
||||||
|
$dropdown-divider-bg: $gray-800 !default;
|
||||||
|
|
||||||
|
$dropdown-link-color: $white !default;
|
||||||
|
$dropdown-link-hover-color: $white !default;
|
||||||
|
$dropdown-link-hover-bg: $primary !default;
|
||||||
|
|
||||||
|
// Navs
|
||||||
|
|
||||||
|
$nav-tabs-border-color: $table-border-color !default;
|
||||||
|
$nav-tabs-link-hover-border-color: $nav-tabs-border-color !default;
|
||||||
|
$nav-tabs-link-active-color: $white !default;
|
||||||
|
$nav-tabs-link-active-bg: $nav-tabs-border-color !default;
|
||||||
|
$nav-tabs-link-active-border-color: $nav-tabs-border-color !default;
|
||||||
|
|
||||||
|
// Navbar
|
||||||
|
|
||||||
|
$navbar-dark-hover-color: $white !default;
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
|
||||||
|
$pagination-color: $white !default;
|
||||||
|
$pagination-bg: $gray-700 !default;
|
||||||
|
$pagination-border-color: transparent !default;
|
||||||
|
|
||||||
|
$pagination-hover-color: $white !default;
|
||||||
|
$pagination-hover-bg: $primary !default;
|
||||||
|
$pagination-hover-border-color: $pagination-border-color !default;
|
||||||
|
|
||||||
|
$pagination-disabled-bg: $pagination-bg !default;
|
||||||
|
$pagination-disabled-border-color: $pagination-border-color !default;
|
||||||
|
|
||||||
|
|
||||||
|
// Jumbotron
|
||||||
|
|
||||||
|
$jumbotron-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
// Cards
|
||||||
|
|
||||||
|
$card-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
// Tooltips
|
||||||
|
|
||||||
|
$tooltip-bg: $gray-700 !default;
|
||||||
|
$tooltip-opacity: 1 !default;
|
||||||
|
|
||||||
|
// Popovers
|
||||||
|
|
||||||
|
$popover-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
// Modals
|
||||||
|
|
||||||
|
$modal-content-bg: $gray-800 !default;
|
||||||
|
|
||||||
|
$modal-header-border-color: $gray-700 !default;
|
||||||
|
|
||||||
|
// Progress bars
|
||||||
|
|
||||||
|
$progress-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
// List group
|
||||||
|
|
||||||
|
$list-group-bg: $gray-800 !default;
|
||||||
|
$list-group-border-color: $gray-700 !default;
|
||||||
|
|
||||||
|
$list-group-hover-bg: $primary !default;
|
||||||
|
|
||||||
|
$list-group-disabled-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
$list-group-action-active-bg: $primary !default;
|
||||||
|
|
||||||
|
// Breadcrumbs
|
||||||
|
|
||||||
|
$breadcrumb-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
// Close
|
||||||
|
|
||||||
|
$close-color: $white !default;
|
||||||
|
$close-text-shadow: none !default;
|
||||||
|
|
||||||
|
// Code
|
||||||
|
|
||||||
|
$pre-color: inherit !default;
|
11022
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cyborg/bootstrap.css
vendored
Normal file
11022
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cyborg/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cyborg/bootstrap.min.css
vendored
Normal file
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/cyborg/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,240 @@
|
|||||||
|
// Darkly 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
|
||||||
|
// Variables ===================================================================
|
||||||
|
|
||||||
|
$web-font-path: "https://fonts.googleapis.com/css?family=Lato:400,700,400italic" !default;
|
||||||
|
@import url($web-font-path);
|
||||||
|
|
||||||
|
// Navbar ======================================================================
|
||||||
|
|
||||||
|
.bg-primary {
|
||||||
|
.navbar-nav .active > .nav-link {
|
||||||
|
color: $success !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-light {
|
||||||
|
&.navbar {
|
||||||
|
background-color: $success !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.navbar-light .navbar-nav {
|
||||||
|
.nav-link:focus,
|
||||||
|
.nav-link:hover,
|
||||||
|
.active > .nav-link {
|
||||||
|
color: $primary !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons =====================================================================
|
||||||
|
|
||||||
|
// Typography ==================================================================
|
||||||
|
|
||||||
|
.blockquote {
|
||||||
|
&-footer {
|
||||||
|
color: $gray-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tables ======================================================================
|
||||||
|
|
||||||
|
.table {
|
||||||
|
|
||||||
|
&-primary {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-secondary {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-light {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-dark {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-success {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-info {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-danger {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-warning {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-active {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $table-active-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-hover {
|
||||||
|
|
||||||
|
.table-primary:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($primary, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-secondary:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($secondary, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-light:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($light, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-dark:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($dark, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-success:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($success, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-info:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($info, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-danger:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($danger, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-warning:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($warning, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-active:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $table-active-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forms =======================================================================
|
||||||
|
|
||||||
|
.input-group-addon {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navs ========================================================================
|
||||||
|
|
||||||
|
.nav-tabs,
|
||||||
|
.nav-pills {
|
||||||
|
|
||||||
|
.nav-link,
|
||||||
|
.nav-link.active,
|
||||||
|
.nav-link.active:focus,
|
||||||
|
.nav-link.active:hover,
|
||||||
|
.nav-item.open .nav-link,
|
||||||
|
.nav-item.open .nav-link:focus,
|
||||||
|
.nav-item.open .nav-link:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicators ==================================================================
|
||||||
|
|
||||||
|
.close {
|
||||||
|
opacity: 0.4;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
border: none;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
a,
|
||||||
|
.alert-link {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $color, $value in $theme-colors {
|
||||||
|
&-#{$color} {
|
||||||
|
@if $enable-gradients {
|
||||||
|
background: $value linear-gradient(180deg, mix($white, $value, 15%), $value) repeat-x;
|
||||||
|
} @else {
|
||||||
|
background-color: $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Progress bars ===============================================================
|
||||||
|
|
||||||
|
// Containers ==================================================================
|
||||||
|
|
||||||
|
|
||||||
|
.list-group-item-action {
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: $gray-700;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item-heading {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,174 @@
|
|||||||
|
// Darkly 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
//
|
||||||
|
// Color system
|
||||||
|
//
|
||||||
|
|
||||||
|
$white: #fff !default;
|
||||||
|
$gray-100: #f8f9fa !default;
|
||||||
|
$gray-200: #ebebeb !default;
|
||||||
|
$gray-300: #dee2e6 !default;
|
||||||
|
$gray-400: #ced4da !default;
|
||||||
|
$gray-500: #adb5bd !default;
|
||||||
|
$gray-600: #999 !default;
|
||||||
|
$gray-700: #444 !default;
|
||||||
|
$gray-800: #303030 !default;
|
||||||
|
$gray-900: #222 !default;
|
||||||
|
$black: #000 !default;
|
||||||
|
|
||||||
|
$blue: #375a7f !default;
|
||||||
|
$indigo: #6610f2 !default;
|
||||||
|
$purple: #6f42c1 !default;
|
||||||
|
$pink: #e83e8c !default;
|
||||||
|
$red: #E74C3C !default;
|
||||||
|
$orange: #fd7e14 !default;
|
||||||
|
$yellow: #F39C12 !default;
|
||||||
|
$green: #00bc8c !default;
|
||||||
|
$teal: #20c997 !default;
|
||||||
|
$cyan: #3498DB !default;
|
||||||
|
|
||||||
|
$primary: $blue !default;
|
||||||
|
$secondary: $gray-700 !default;
|
||||||
|
$success: $green !default;
|
||||||
|
$info: $cyan !default;
|
||||||
|
$warning: $yellow !default;
|
||||||
|
$danger: $red !default;
|
||||||
|
$light: $gray-600 !default;
|
||||||
|
$dark: $gray-800 !default;
|
||||||
|
|
||||||
|
$yiq-contrasted-threshold: 175 !default;
|
||||||
|
|
||||||
|
// Body
|
||||||
|
|
||||||
|
$body-bg: $gray-900 !default;
|
||||||
|
$body-color: $white !default;
|
||||||
|
|
||||||
|
// Links
|
||||||
|
|
||||||
|
$link-color: $success !default;
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
|
||||||
|
$font-family-sans-serif: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
|
||||||
|
|
||||||
|
$font-size-base: 0.9375rem !default;
|
||||||
|
|
||||||
|
$h1-font-size: 3rem !default;
|
||||||
|
$h2-font-size: 2.5rem !default;
|
||||||
|
$h3-font-size: 2rem !default;
|
||||||
|
|
||||||
|
// Tables
|
||||||
|
|
||||||
|
$table-accent-bg: $gray-800 !default;
|
||||||
|
|
||||||
|
$table-border-color: $gray-700 !default;
|
||||||
|
|
||||||
|
// Forms
|
||||||
|
|
||||||
|
$input-border-color: $body-bg !default;
|
||||||
|
|
||||||
|
$input-group-addon-color: $gray-500 !default;
|
||||||
|
$input-group-addon-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
$custom-file-color: $gray-500 !default;
|
||||||
|
$custom-file-border-color: $body-bg !default;
|
||||||
|
|
||||||
|
// Dropdowns
|
||||||
|
|
||||||
|
$dropdown-bg: $gray-900 !default;
|
||||||
|
$dropdown-border-color: $gray-700 !default;
|
||||||
|
$dropdown-divider-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
$dropdown-link-color: $white !default;
|
||||||
|
$dropdown-link-hover-color: $white !default;
|
||||||
|
$dropdown-link-hover-bg: $primary !default;
|
||||||
|
|
||||||
|
// Navs
|
||||||
|
|
||||||
|
$nav-link-padding-x: 2rem !default;
|
||||||
|
$nav-link-disabled-color: $gray-500 !default;
|
||||||
|
|
||||||
|
$nav-tabs-border-color: $gray-700 !default;
|
||||||
|
$nav-tabs-link-hover-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent !default;
|
||||||
|
$nav-tabs-link-active-color: $white !default;
|
||||||
|
$nav-tabs-link-active-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent !default;
|
||||||
|
|
||||||
|
// Navbar
|
||||||
|
|
||||||
|
$navbar-padding-y: 1rem !default;
|
||||||
|
|
||||||
|
$navbar-dark-color: rgba($white,.6) !default;
|
||||||
|
$navbar-dark-hover-color: $white !default;
|
||||||
|
|
||||||
|
$navbar-light-color: $white !default;
|
||||||
|
$navbar-light-hover-color: $success !default;
|
||||||
|
$navbar-light-active-color: $white !default;
|
||||||
|
$navbar-light-disabled-color: rgba($white,.3) !default;
|
||||||
|
$navbar-light-toggler-border-color: rgba($white,.1) !default;
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
|
||||||
|
$pagination-color: $white !default;
|
||||||
|
$pagination-bg: $success !default;
|
||||||
|
$pagination-border-width: 0 !default;
|
||||||
|
$pagination-border-color: transparent !default;
|
||||||
|
|
||||||
|
$pagination-hover-color: $white !default;
|
||||||
|
$pagination-hover-bg: lighten($success, 10%) !default;
|
||||||
|
$pagination-hover-border-color: transparent !default;
|
||||||
|
|
||||||
|
$pagination-active-bg: $pagination-hover-bg !default;
|
||||||
|
$pagination-active-border-color: transparent !default;
|
||||||
|
|
||||||
|
$pagination-disabled-color: $white !default;
|
||||||
|
$pagination-disabled-bg: darken($success, 15%) !default;
|
||||||
|
$pagination-disabled-border-color: transparent !default;
|
||||||
|
|
||||||
|
// Jumbotron
|
||||||
|
|
||||||
|
$jumbotron-bg: $gray-800 !default;
|
||||||
|
|
||||||
|
// Cards
|
||||||
|
|
||||||
|
$card-cap-bg: $gray-700 !default;
|
||||||
|
$card-bg: $gray-800 !default;
|
||||||
|
|
||||||
|
// Popovers
|
||||||
|
|
||||||
|
$popover-bg: $gray-800 !default;
|
||||||
|
|
||||||
|
$popover-header-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
// Modals
|
||||||
|
|
||||||
|
$modal-content-bg: $gray-800 !default;
|
||||||
|
$modal-content-border-color: $gray-700 !default;
|
||||||
|
|
||||||
|
$modal-header-border-color: $gray-700 !default;
|
||||||
|
|
||||||
|
// Progress bars
|
||||||
|
|
||||||
|
$progress-height: 0.625rem !default;
|
||||||
|
$progress-font-size: 0.625rem !default;
|
||||||
|
$progress-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
// List group
|
||||||
|
|
||||||
|
$list-group-bg: $gray-800 !default;
|
||||||
|
$list-group-border-color: $gray-700 !default;
|
||||||
|
|
||||||
|
$list-group-hover-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
// Breadcrumbs
|
||||||
|
|
||||||
|
$breadcrumb-bg: $gray-700 !default;
|
||||||
|
|
||||||
|
// Close
|
||||||
|
|
||||||
|
$close-color: $white !default;
|
||||||
|
$close-text-shadow: none !default;
|
||||||
|
|
||||||
|
// Code
|
||||||
|
|
||||||
|
$pre-color: inherit !default;
|
10954
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/darkly/bootstrap.css
vendored
Normal file
10954
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/darkly/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/darkly/bootstrap.min.css
vendored
Normal file
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/darkly/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
10224
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/default/bootstrap.css
vendored
Normal file
10224
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/default/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/default/bootstrap.min.css
vendored
Normal file
7
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/default/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,247 @@
|
|||||||
|
// Flatly 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
|
||||||
|
// Variables ===================================================================
|
||||||
|
|
||||||
|
$web-font-path: "https://fonts.googleapis.com/css?family=Lato:400,700,400italic" !default;
|
||||||
|
@import url($web-font-path);
|
||||||
|
|
||||||
|
// Navbar =======================================================================
|
||||||
|
|
||||||
|
.bg-primary {
|
||||||
|
.navbar-nav .active > .nav-link {
|
||||||
|
color: $success !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-dark {
|
||||||
|
background-color: $success !important;
|
||||||
|
&.navbar-dark .navbar-nav {
|
||||||
|
.nav-link:focus,
|
||||||
|
.nav-link:hover,
|
||||||
|
.active > .nav-link {
|
||||||
|
color: $primary !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons =====================================================================
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
&-secondary,
|
||||||
|
&-secondary:hover,
|
||||||
|
&-warning,
|
||||||
|
&-warning:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typography ==================================================================
|
||||||
|
|
||||||
|
// Tables ======================================================================
|
||||||
|
|
||||||
|
.table {
|
||||||
|
|
||||||
|
&-primary,
|
||||||
|
&-secondary,
|
||||||
|
&-success,
|
||||||
|
&-info,
|
||||||
|
&-warning,
|
||||||
|
&-danger {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-primary {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-secondary {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-light {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-dark {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-success {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-info {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-danger {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-warning {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-active {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $table-active-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-hover {
|
||||||
|
|
||||||
|
.table-primary:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($primary, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-secondary:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($secondary, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-light:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($light, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-dark:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($dark, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-success:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($success, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-info:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($info, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-danger:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($danger, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-warning:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($warning, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-active:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $table-active-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forms =======================================================================
|
||||||
|
|
||||||
|
// Navs ========================================================================
|
||||||
|
|
||||||
|
.nav-tabs {
|
||||||
|
.nav-link.active,
|
||||||
|
.nav-link.active:focus,
|
||||||
|
.nav-link.active:hover,
|
||||||
|
.nav-item.open .nav-link,
|
||||||
|
.nav-item.open .nav-link:focus,
|
||||||
|
.nav-item.open .nav-link:hover {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicators ==================================================================
|
||||||
|
|
||||||
|
.close {
|
||||||
|
text-decoration: none;
|
||||||
|
opacity: 0.4;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
&-secondary,
|
||||||
|
&-warning {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
border: none;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
a,
|
||||||
|
.alert-link {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $color, $value in $theme-colors {
|
||||||
|
&-#{$color} {
|
||||||
|
@if $enable-gradients {
|
||||||
|
background: $value linear-gradient(180deg, mix($body-bg, $value, 15%), $value) repeat-x;
|
||||||
|
} @else {
|
||||||
|
background-color: $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-light {
|
||||||
|
&,
|
||||||
|
& a,
|
||||||
|
& .alert-link {
|
||||||
|
color: $body-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Progress bars ===============================================================
|
||||||
|
|
||||||
|
// Containers ==================================================================
|
||||||
|
.modal .close{
|
||||||
|
color: $black;
|
||||||
|
|
||||||
|
&:not(:disabled):not(.disabled):hover,
|
||||||
|
&:not(:disabled):not(.disabled):focus {
|
||||||
|
color: $black;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
// Flatly 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
//
|
||||||
|
// Color system
|
||||||
|
//
|
||||||
|
|
||||||
|
$white: #fff !default;
|
||||||
|
$gray-100: #f8f9fa !default;
|
||||||
|
$gray-200: #ecf0f1 !default;
|
||||||
|
$gray-300: #dee2e6 !default;
|
||||||
|
$gray-400: #ced4da !default;
|
||||||
|
$gray-500: #b4bcc2 !default;
|
||||||
|
$gray-600: #95a5a6 !default;
|
||||||
|
$gray-700: #7b8a8b !default;
|
||||||
|
$gray-800: #343a40 !default;
|
||||||
|
$gray-900: #212529 !default;
|
||||||
|
$black: #000 !default;
|
||||||
|
|
||||||
|
$blue: #2C3E50 !default;
|
||||||
|
$indigo: #6610f2 !default;
|
||||||
|
$purple: #6f42c1 !default;
|
||||||
|
$pink: #e83e8c !default;
|
||||||
|
$red: #E74C3C !default;
|
||||||
|
$orange: #fd7e14 !default;
|
||||||
|
$yellow: #F39C12 !default;
|
||||||
|
$green: #18BC9C !default;
|
||||||
|
$teal: #20c997 !default;
|
||||||
|
$cyan: #3498DB !default;
|
||||||
|
|
||||||
|
$primary: $blue !default;
|
||||||
|
$secondary: $gray-600 !default;
|
||||||
|
$success: $green !default;
|
||||||
|
$info: $cyan !default;
|
||||||
|
$warning: $yellow !default;
|
||||||
|
$danger: $red !default;
|
||||||
|
$light: $gray-200 !default;
|
||||||
|
$dark: $gray-700 !default;
|
||||||
|
|
||||||
|
$yiq-contrasted-threshold: 175 !default;
|
||||||
|
|
||||||
|
// Links
|
||||||
|
|
||||||
|
$link-color: $success !default;
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
|
||||||
|
$font-family-sans-serif: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
|
||||||
|
|
||||||
|
$font-size-base: 0.9375rem !default;
|
||||||
|
|
||||||
|
$h1-font-size: 3rem !default;
|
||||||
|
$h2-font-size: 2.5rem !default;
|
||||||
|
$h3-font-size: 2rem !default;
|
||||||
|
|
||||||
|
// Tables
|
||||||
|
|
||||||
|
$table-accent-bg: $gray-200 !default;
|
||||||
|
|
||||||
|
// Dropdowns
|
||||||
|
|
||||||
|
$dropdown-link-color: $gray-700 !default;
|
||||||
|
$dropdown-link-hover-color: $white !default;
|
||||||
|
$dropdown-link-hover-bg: $primary !default;
|
||||||
|
|
||||||
|
// Navs
|
||||||
|
|
||||||
|
$nav-link-padding-y: .5rem !default !default;
|
||||||
|
$nav-link-padding-x: 2rem !default;
|
||||||
|
$nav-link-disabled-color: $gray-600 !default !default;
|
||||||
|
|
||||||
|
$nav-tabs-border-color: $gray-200 !default;
|
||||||
|
|
||||||
|
// Navbar
|
||||||
|
|
||||||
|
$navbar-padding-y: 1rem !default;
|
||||||
|
|
||||||
|
$navbar-dark-color: $white !default;
|
||||||
|
$navbar-dark-hover-color: $success !default;
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
|
||||||
|
$pagination-color: $white !default;
|
||||||
|
$pagination-bg: $success !default;
|
||||||
|
$pagination-border-width: 0 !default;
|
||||||
|
$pagination-border-color: transparent !default;
|
||||||
|
|
||||||
|
$pagination-hover-color: $white !default;
|
||||||
|
$pagination-hover-bg: darken($success, 15%) !default;
|
||||||
|
$pagination-hover-border-color: transparent !default;
|
||||||
|
|
||||||
|
$pagination-active-bg: $pagination-hover-bg !default;
|
||||||
|
$pagination-active-border-color: transparent !default;
|
||||||
|
|
||||||
|
$pagination-disabled-color: $gray-200 !default;
|
||||||
|
$pagination-disabled-bg: lighten($success, 15%) !default;
|
||||||
|
$pagination-disabled-border-color: transparent !default;
|
||||||
|
|
||||||
|
// Progress bars
|
||||||
|
|
||||||
|
$progress-height: 0.625rem !default;
|
||||||
|
$progress-font-size: 0.625rem !default;
|
||||||
|
|
||||||
|
// List group
|
||||||
|
|
||||||
|
$list-group-hover-bg: $gray-200 !default;
|
||||||
|
|
||||||
|
$list-group-disabled-bg: $gray-200 !default;
|
||||||
|
|
||||||
|
// Close
|
||||||
|
|
||||||
|
$close-color: $white !default;
|
||||||
|
$close-text-shadow: none !default;
|
10948
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/flatly/bootstrap.css
vendored
Normal file
10948
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/flatly/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/flatly/bootstrap.min.css
vendored
Normal file
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/flatly/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,73 @@
|
|||||||
|
// Journal 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
|
||||||
|
// Variables ===================================================================
|
||||||
|
|
||||||
|
$web-font-path: "https://fonts.googleapis.com/css?family=News+Cycle:400,700" !default;
|
||||||
|
@import url($web-font-path);
|
||||||
|
|
||||||
|
// Navbar ======================================================================
|
||||||
|
|
||||||
|
.bg-dark {
|
||||||
|
background-color: #000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-light {
|
||||||
|
background-color: $white !important;
|
||||||
|
color: $black;
|
||||||
|
border: 1px solid $gray-200;
|
||||||
|
|
||||||
|
&.navbar-fixed-top {
|
||||||
|
border-width: 0 0 1px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.navbar-fixed-bottom {
|
||||||
|
border-width: 1px 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
font-size: 18px;
|
||||||
|
font-family: $headings-font-family;
|
||||||
|
font-weight: $headings-font-weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand {
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: $headings-font-weight;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons =====================================================================
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
font-family: $headings-font-family;
|
||||||
|
font-weight: $headings-font-weight;
|
||||||
|
|
||||||
|
&-secondary,
|
||||||
|
&-warning {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typography ==================================================================
|
||||||
|
|
||||||
|
// Tables ======================================================================
|
||||||
|
|
||||||
|
// Forms =======================================================================
|
||||||
|
|
||||||
|
// Navs ========================================================================
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicators ==================================================================
|
||||||
|
|
||||||
|
// Progress bars ===============================================================
|
||||||
|
|
||||||
|
// Containers ==================================================================
|
@ -0,0 +1,60 @@
|
|||||||
|
// Journal 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
//
|
||||||
|
// Color system
|
||||||
|
//
|
||||||
|
|
||||||
|
$white: #fff !default;
|
||||||
|
$gray-100: #f8f9fa !default;
|
||||||
|
$gray-200: #eee !default;
|
||||||
|
$gray-300: #dee2e6 !default;
|
||||||
|
$gray-400: #ced4da !default;
|
||||||
|
$gray-500: #aaa !default;
|
||||||
|
$gray-600: #777 !default;
|
||||||
|
$gray-700: #495057 !default;
|
||||||
|
$gray-800: #333 !default;
|
||||||
|
$gray-900: #222 !default;
|
||||||
|
$black: #000 !default;
|
||||||
|
|
||||||
|
$blue: #EB6864 !default;
|
||||||
|
$indigo: #6610f2 !default;
|
||||||
|
$purple: #6f42c1 !default;
|
||||||
|
$pink: #e83e8c !default;
|
||||||
|
$red: #F57A00 !default;
|
||||||
|
$orange: #fd7e14 !default;
|
||||||
|
$yellow: #F5E625 !default;
|
||||||
|
$green: #22B24C !default;
|
||||||
|
$teal: #20c997 !default;
|
||||||
|
$cyan: #369 !default;
|
||||||
|
|
||||||
|
$primary: $blue !default;
|
||||||
|
$secondary: $gray-500 !default;
|
||||||
|
$success: $green !default;
|
||||||
|
$info: $cyan !default;
|
||||||
|
$warning: $yellow !default;
|
||||||
|
$danger: $red !default;
|
||||||
|
$light: $gray-100 !default;
|
||||||
|
$dark: $gray-900 !default;
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
|
||||||
|
$headings-font-family: "News Cycle", "Arial Narrow Bold", sans-serif !default;
|
||||||
|
$headings-font-weight: 700 !default;
|
||||||
|
$headings-line-height: 1.1 !default;
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
|
||||||
|
$input-btn-padding-x: 1rem !default;
|
||||||
|
|
||||||
|
// Navbar
|
||||||
|
|
||||||
|
$navbar-light-color: rgba($black,.7) !default;
|
||||||
|
$navbar-light-hover-color: $black !default;
|
||||||
|
$navbar-light-active-color: $black !default;
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
|
||||||
|
$pagination-hover-color: $white !default;
|
||||||
|
$pagination-hover-bg: $primary !default;
|
||||||
|
$pagination-hover-border-color: $primary !default;
|
10798
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/journal/bootstrap.css
vendored
Normal file
10798
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/journal/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/journal/bootstrap.min.css
vendored
Normal file
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/journal/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,255 @@
|
|||||||
|
// Litera 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
|
||||||
|
// Variables ===================================================================
|
||||||
|
|
||||||
|
$font-family-serif: Georgia, Cambria, "Times New Roman", Times, serif !default;
|
||||||
|
|
||||||
|
// Navbar ======================================================================
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
|
&.bg-dark {
|
||||||
|
background-color: $success !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bg-light {
|
||||||
|
background-color: #fff !important;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
&.navbar-fixed-top {
|
||||||
|
border-width: 0 0 1px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.navbar-fixed-bottom {
|
||||||
|
border-width: 1px 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons =====================================================================
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
border-radius: 1.078em;
|
||||||
|
|
||||||
|
&-lg {
|
||||||
|
border-radius: 2.688em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-sm {
|
||||||
|
border-radius: 0.844em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typography ==================================================================
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-family: $font-family-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lead {
|
||||||
|
color: $gray-600;
|
||||||
|
font-family: $font-family-sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tables ======================================================================
|
||||||
|
|
||||||
|
table,
|
||||||
|
.table {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
|
&-primary,
|
||||||
|
&-secondary,
|
||||||
|
&-success,
|
||||||
|
&-info,
|
||||||
|
&-warning,
|
||||||
|
&-danger {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
|
||||||
|
&-primary {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-secondary {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-light {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-dark {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-success {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-info {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-danger {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-warning {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-active {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $table-active-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-hover {
|
||||||
|
|
||||||
|
.table-primary:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($primary, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-secondary:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($secondary, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-light:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($light, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-dark:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($dark, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-success:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($success, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-info:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($info, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-danger:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($danger, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-warning:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: darken($warning, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-active:hover {
|
||||||
|
&, > th, > td {
|
||||||
|
background-color: $table-active-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forms =======================================================================
|
||||||
|
|
||||||
|
// Navs ========================================================================
|
||||||
|
|
||||||
|
.nav,
|
||||||
|
.breadcrumb,
|
||||||
|
.pagination {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicators ==================================================================
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
color: $white;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
|
&, p {
|
||||||
|
font-family: $font-family-sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, .alert-link {
|
||||||
|
color: #fff;
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $color, $value in $theme-colors {
|
||||||
|
&-#{$color} {
|
||||||
|
@if $enable-gradients {
|
||||||
|
background: $value linear-gradient(0deg, mix($body-bg, $value, 15%), $value) repeat-x;
|
||||||
|
} @else {
|
||||||
|
background-color: $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-light {
|
||||||
|
&,
|
||||||
|
& a,
|
||||||
|
& .alert-link {
|
||||||
|
color: $body-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Progress bars ===============================================================
|
||||||
|
|
||||||
|
// Containers ==================================================================
|
||||||
|
|
||||||
|
.list-group {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
// Litera 4.3.1
|
||||||
|
// Bootswatch
|
||||||
|
|
||||||
|
//
|
||||||
|
// Color system
|
||||||
|
//
|
||||||
|
|
||||||
|
$white: #fff !default;
|
||||||
|
$gray-100: #f8f9fa !default;
|
||||||
|
$gray-200: #e9ecef !default;
|
||||||
|
$gray-300: #ddd !default;
|
||||||
|
$gray-400: #ced4da !default;
|
||||||
|
$gray-500: #adb5bd !default;
|
||||||
|
$gray-600: #868e96 !default;
|
||||||
|
$gray-700: #495057 !default;
|
||||||
|
$gray-800: #343a40 !default;
|
||||||
|
$gray-900: #212529 !default;
|
||||||
|
$black: #000 !default;
|
||||||
|
|
||||||
|
$blue: #4582EC !default;
|
||||||
|
$indigo: #6610f2 !default;
|
||||||
|
$purple: #6f42c1 !default;
|
||||||
|
$pink: #e83e8c !default;
|
||||||
|
$red: #d9534f !default;
|
||||||
|
$orange: #fd7e14 !default;
|
||||||
|
$yellow: #f0ad4e !default;
|
||||||
|
$green: #02B875 !default;
|
||||||
|
$teal: #20c997 !default;
|
||||||
|
$cyan: #17a2b8 !default;
|
||||||
|
|
||||||
|
$primary: $blue !default;
|
||||||
|
$secondary: $gray-500 !default;
|
||||||
|
$success: $green !default;
|
||||||
|
$info: $cyan !default;
|
||||||
|
$warning: $yellow !default;
|
||||||
|
$danger: $red !default;
|
||||||
|
$light: $gray-100 !default;
|
||||||
|
$dark: $gray-800 !default;
|
||||||
|
|
||||||
|
$yiq-contrasted-threshold: 190 !default;
|
||||||
|
|
||||||
|
// Body
|
||||||
|
|
||||||
|
$body-color: $gray-800 !default;
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
|
||||||
|
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default;
|
||||||
|
|
||||||
|
$font-size-base: 1.063rem !default;
|
||||||
|
|
||||||
|
$headings-font-weight: 700 !default;
|
||||||
|
|
||||||
|
// Tables
|
||||||
|
|
||||||
|
$table-border-color: rgba(0,0,0,0.1) !default;
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
|
||||||
|
$input-btn-padding-y: 0.5rem !default;
|
||||||
|
$input-btn-padding-x: 1.1rem !default;
|
||||||
|
|
||||||
|
$btn-font-family: $font-family-sans-serif !default;
|
||||||
|
$btn-font-size: 0.875rem !default;
|
||||||
|
|
||||||
|
$btn-font-size-sm: 0.688rem !default;
|
||||||
|
|
||||||
|
// Forms
|
||||||
|
|
||||||
|
$input-border-color: rgba(0,0,0,.1) !default;
|
||||||
|
|
||||||
|
$input-group-addon-bg: $gray-200 !default !default;
|
||||||
|
|
||||||
|
// Navbar
|
||||||
|
|
||||||
|
$navbar-dark-color: rgba($white,.6) !default;
|
||||||
|
$navbar-dark-hover-color: $white !default;
|
||||||
|
|
||||||
|
$navbar-light-hover-color: $body-color !default;
|
||||||
|
$navbar-light-active-color: $body-color !default;
|
||||||
|
|
||||||
|
// Tooltips
|
||||||
|
|
||||||
|
$tooltip-font-size: 11px !default;
|
||||||
|
|
||||||
|
// Badges
|
||||||
|
|
||||||
|
$badge-font-weight: normal !default;
|
||||||
|
$badge-padding-y: 0.6em !default;
|
||||||
|
$badge-padding-x: 1.2em !default;
|
||||||
|
|
||||||
|
// Alerts
|
||||||
|
|
||||||
|
$alert-border-width: 0 !default;
|
10979
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/litera/bootstrap.css
vendored
Normal file
10979
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/litera/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/litera/bootstrap.min.css
vendored
Normal file
12
src/epicmorg.jira.issue.web.reporter/wwwroot/lib/bootstrap/themes/litera/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user