mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-14 17:22:54 -07:00
Started #298
This commit is contained in:
parent
071daf4ab4
commit
0dd30968d5
22 changed files with 8276 additions and 252 deletions
|
@ -77,6 +77,7 @@
|
||||||
<Compile Include="Models\UserProperties.cs" />
|
<Compile Include="Models\UserProperties.cs" />
|
||||||
<Compile Include="SettingModels\AuthenticationSettings.cs" />
|
<Compile Include="SettingModels\AuthenticationSettings.cs" />
|
||||||
<Compile Include="SettingModels\HeadphonesSettings.cs" />
|
<Compile Include="SettingModels\HeadphonesSettings.cs" />
|
||||||
|
<Compile Include="SettingModels\LandingPageSettings.cs" />
|
||||||
<Compile Include="SettingModels\SlackNotificationSettings.cs" />
|
<Compile Include="SettingModels\SlackNotificationSettings.cs" />
|
||||||
<Compile Include="SettingModels\PushoverNotificationSettings.cs" />
|
<Compile Include="SettingModels\PushoverNotificationSettings.cs" />
|
||||||
<Compile Include="SettingModels\PushBulletNotificationSettings.cs" />
|
<Compile Include="SettingModels\PushBulletNotificationSettings.cs" />
|
||||||
|
|
40
PlexRequests.Core/SettingModels/LandingPageSettings.cs
Normal file
40
PlexRequests.Core/SettingModels/LandingPageSettings.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: LandingPageSettings.cs
|
||||||
|
// Created By: Jamie Rees
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// ************************************************************************/
|
||||||
|
#endregion
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PlexRequests.Core.SettingModels
|
||||||
|
{
|
||||||
|
public class LandingPageSettings : Settings
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public bool NoticeEnable { get; set; }
|
||||||
|
public string NoticeMessage { get; set; }
|
||||||
|
public bool EnabledNoticeTime { get; set; }
|
||||||
|
public DateTime NoticeStart { get; set; }
|
||||||
|
public DateTime NoticeEnd { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,6 +74,7 @@ namespace PlexRequests.UI.Tests
|
||||||
private Mock<ICacheProvider> Cache { get; set; }
|
private Mock<ICacheProvider> Cache { get; set; }
|
||||||
private Mock<ISettingsService<LogSettings>> Log { get; set; }
|
private Mock<ISettingsService<LogSettings>> Log { get; set; }
|
||||||
private Mock<ISettingsService<SlackNotificationSettings>> SlackSettings { get; set; }
|
private Mock<ISettingsService<SlackNotificationSettings>> SlackSettings { get; set; }
|
||||||
|
private Mock<ISettingsService<LandingPageSettings>> LandingPageSettings { get; set; }
|
||||||
private Mock<ISlackApi> SlackApi { get; set; }
|
private Mock<ISlackApi> SlackApi { get; set; }
|
||||||
|
|
||||||
private ConfigurableBootstrapper Bootstrapper { get; set; }
|
private ConfigurableBootstrapper Bootstrapper { get; set; }
|
||||||
|
@ -109,6 +110,8 @@ namespace PlexRequests.UI.Tests
|
||||||
Log = new Mock<ISettingsService<LogSettings>>();
|
Log = new Mock<ISettingsService<LogSettings>>();
|
||||||
SlackApi = new Mock<ISlackApi>();
|
SlackApi = new Mock<ISlackApi>();
|
||||||
SlackSettings = new Mock<ISettingsService<SlackNotificationSettings>>();
|
SlackSettings = new Mock<ISettingsService<SlackNotificationSettings>>();
|
||||||
|
LandingPageSettings = new Mock<ISettingsService<LandingPageSettings>>();
|
||||||
|
|
||||||
|
|
||||||
Bootstrapper = new ConfigurableBootstrapper(with =>
|
Bootstrapper = new ConfigurableBootstrapper(with =>
|
||||||
{
|
{
|
||||||
|
@ -133,6 +136,7 @@ namespace PlexRequests.UI.Tests
|
||||||
with.Dependency(Cache.Object);
|
with.Dependency(Cache.Object);
|
||||||
with.Dependency(Log.Object);
|
with.Dependency(Log.Object);
|
||||||
with.Dependency(SlackApi.Object);
|
with.Dependency(SlackApi.Object);
|
||||||
|
with.Dependency(LandingPageSettings.Object);
|
||||||
with.Dependency(SlackSettings.Object);
|
with.Dependency(SlackSettings.Object);
|
||||||
with.RootPathProvider<TestRootPathProvider>();
|
with.RootPathProvider<TestRootPathProvider>();
|
||||||
with.RequestStartup((container, pipelines, context) =>
|
with.RequestStartup((container, pipelines, context) =>
|
||||||
|
|
|
@ -81,6 +81,7 @@ namespace PlexRequests.UI
|
||||||
container.Register<ISettingsService<HeadphonesSettings>, SettingsServiceV2<HeadphonesSettings>>();
|
container.Register<ISettingsService<HeadphonesSettings>, SettingsServiceV2<HeadphonesSettings>>();
|
||||||
container.Register<ISettingsService<LogSettings>, SettingsServiceV2<LogSettings>>();
|
container.Register<ISettingsService<LogSettings>, SettingsServiceV2<LogSettings>>();
|
||||||
container.Register<ISettingsService<SlackNotificationSettings>, SettingsServiceV2<SlackNotificationSettings>>();
|
container.Register<ISettingsService<SlackNotificationSettings>, SettingsServiceV2<SlackNotificationSettings>>();
|
||||||
|
container.Register<ISettingsService<LandingPageSettings>, SettingsServiceV2<LandingPageSettings>>();
|
||||||
|
|
||||||
// Repo's
|
// Repo's
|
||||||
container.Register<IRepository<LogEntity>, GenericRepository<LogEntity>>();
|
container.Register<IRepository<LogEntity>, GenericRepository<LogEntity>>();
|
||||||
|
|
|
@ -1,250 +0,0 @@
|
||||||
|
|
||||||
//
|
|
||||||
// Checkboxes
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
$font-family-icon: 'FontAwesome' !default;
|
|
||||||
$fa-var-check: "\f00c" !default;
|
|
||||||
$check-icon: $fa-var-check !default;
|
|
||||||
|
|
||||||
@mixin checkbox-variant($parent, $color) {
|
|
||||||
#{$parent} input[type="checkbox"]:checked + label,
|
|
||||||
#{$parent} input[type="radio"]:checked + label {
|
|
||||||
&::before {
|
|
||||||
background-color: $color;
|
|
||||||
border-color: $color;
|
|
||||||
}
|
|
||||||
&::after{
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin checkbox-variant-indeterminate($parent, $color) {
|
|
||||||
#{$parent} input[type="checkbox"]:indeterminate + label,
|
|
||||||
#{$parent} input[type="radio"]:indeterminate + label {
|
|
||||||
&::before {
|
|
||||||
background-color: $color;
|
|
||||||
border-color: $color;
|
|
||||||
}
|
|
||||||
&::after{
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.abc-checkbox{
|
|
||||||
padding-left: 20px;
|
|
||||||
|
|
||||||
label{
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
position: relative;
|
|
||||||
padding-left: 5px;
|
|
||||||
|
|
||||||
&::before{
|
|
||||||
cursor: pointer;
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
width: 17px;
|
|
||||||
height: 17px;
|
|
||||||
left: 0;
|
|
||||||
margin-left: -20px;
|
|
||||||
border: 1px solid $input-border-color;
|
|
||||||
border-radius: 3px;
|
|
||||||
background-color: #fff;
|
|
||||||
@include transition(border 0.15s ease-in-out, color 0.15s ease-in-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after{
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
margin-left: -20px;
|
|
||||||
padding-left: 3px;
|
|
||||||
padding-top: 1px;
|
|
||||||
font-size: 11px;
|
|
||||||
color: $input-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"],
|
|
||||||
input[type="radio"] {
|
|
||||||
cursor: pointer;
|
|
||||||
opacity: 0;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
&:focus + label::before{
|
|
||||||
@include tab-focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
&:checked + label::after{
|
|
||||||
font-family: $font-family-icon;
|
|
||||||
content: $check-icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:indeterminate + label::after{
|
|
||||||
display: block;
|
|
||||||
content: "";
|
|
||||||
width: 10px;
|
|
||||||
height: 3px;
|
|
||||||
background-color: #555555;
|
|
||||||
border-radius: 2px;
|
|
||||||
margin-left: -16.5px;
|
|
||||||
margin-top: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled + label{
|
|
||||||
opacity: 0.65;
|
|
||||||
|
|
||||||
&::before{
|
|
||||||
background-color: $input-bg-disabled;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
&.abc-checkbox-circle label::before{
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.checkbox-inline{
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include checkbox-variant('.abc-checkbox-primary', $brand-primary);
|
|
||||||
@include checkbox-variant('.abc-checkbox-danger', $brand-danger);
|
|
||||||
@include checkbox-variant('.abc-checkbox-info', $brand-info);
|
|
||||||
@include checkbox-variant('.abc-checkbox-warning', $brand-warning);
|
|
||||||
@include checkbox-variant('.abc-checkbox-success', $brand-success);
|
|
||||||
|
|
||||||
|
|
||||||
@include checkbox-variant-indeterminate('.abc-checkbox-primary', $brand-primary);
|
|
||||||
@include checkbox-variant-indeterminate('.abc-checkbox-danger', $brand-danger);
|
|
||||||
@include checkbox-variant-indeterminate('.abc-checkbox-info', $brand-info);
|
|
||||||
@include checkbox-variant-indeterminate('.abc-checkbox-warning', $brand-warning);
|
|
||||||
@include checkbox-variant-indeterminate('.abc-checkbox-success', $brand-success);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Radios
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
@mixin radio-variant($parent, $color) {
|
|
||||||
#{$parent} input[type="radio"]{
|
|
||||||
+ label{
|
|
||||||
&::after{
|
|
||||||
background-color: $color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:checked + label{
|
|
||||||
&::before {
|
|
||||||
border-color: $color;
|
|
||||||
}
|
|
||||||
&::after{
|
|
||||||
background-color: $color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.abc-radio{
|
|
||||||
padding-left: 20px;
|
|
||||||
|
|
||||||
label{
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
position: relative;
|
|
||||||
padding-left: 5px;
|
|
||||||
|
|
||||||
&::before{
|
|
||||||
cursor: pointer;
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
width: 17px;
|
|
||||||
height: 17px;
|
|
||||||
left: 0;
|
|
||||||
margin-left: -20px;
|
|
||||||
border: 1px solid $input-border-color;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: #fff;
|
|
||||||
@include transition(border 0.15s ease-in-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after{
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
content: " ";
|
|
||||||
width: 11px;
|
|
||||||
height: 11px;
|
|
||||||
left: 3px;
|
|
||||||
top: 3px;
|
|
||||||
margin-left: -20px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: $input-color;
|
|
||||||
transform: scale(0, 0);
|
|
||||||
|
|
||||||
transition: transform .1s cubic-bezier(.8,-0.33,.2,1.33);
|
|
||||||
//curve - http://cubic-bezier.com/#.8,-0.33,.2,1.33
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="radio"]{
|
|
||||||
cursor: pointer;
|
|
||||||
opacity: 0;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
&:focus + label::before{
|
|
||||||
@include tab-focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
&:checked + label::after{
|
|
||||||
transform: scale(1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:disabled + label{
|
|
||||||
opacity: 0.65;
|
|
||||||
|
|
||||||
&::before{
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
&.radio-inline{
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include radio-variant('.abc-radio-primary', $brand-primary);
|
|
||||||
@include radio-variant('.abc-radio-danger', $brand-danger);
|
|
||||||
@include radio-variant('.abc-radio-info', $brand-info);
|
|
||||||
@include radio-variant('.abc-radio-warning', $brand-warning);
|
|
||||||
@include radio-variant('.abc-radio-success', $brand-success);
|
|
||||||
|
|
||||||
|
|
||||||
input[type="checkbox"],
|
|
||||||
input[type="radio"] {
|
|
||||||
&.styled:checked + label:after {
|
|
||||||
font-family: $font-family-icon;
|
|
||||||
content: $check-icon;
|
|
||||||
}
|
|
||||||
.styled:checked + label {
|
|
||||||
&::before {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
&::after {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
17
PlexRequests.UI/Content/bootstrap-datetimepicker-build.less
vendored
Normal file
17
PlexRequests.UI/Content/bootstrap-datetimepicker-build.less
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Import bootstrap variables including default color palette and fonts
|
||||||
|
@import "bootstrap/less/variables.less";
|
||||||
|
|
||||||
|
// Import datepicker component
|
||||||
|
@import "_bootstrap-datetimepicker.less";
|
||||||
|
|
||||||
|
//this is here so the compiler doesn't complain about a missing bootstrap mixin
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0,0,0,0);
|
||||||
|
border: 0;
|
||||||
|
}
|
2552
PlexRequests.UI/Content/bootstrap-datetimepicker.min.js
vendored
Normal file
2552
PlexRequests.UI/Content/bootstrap-datetimepicker.min.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
202
PlexRequests.UI/Content/datepicker.css
Normal file
202
PlexRequests.UI/Content/datepicker.css
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
/*!
|
||||||
|
* Datetimepicker for Bootstrap 3
|
||||||
|
* ! version : 4.7.14
|
||||||
|
* https://github.com/Eonasdan/bootstrap-datetimepicker/
|
||||||
|
*/
|
||||||
|
.sr-only, .bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after, .bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after, .bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after, .bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after, .bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after, .bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after, .bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after, .bootstrap-datetimepicker-widget .btn[data-action="clear"]::after, .bootstrap-datetimepicker-widget .btn[data-action="today"]::after, .bootstrap-datetimepicker-widget .picker-switch::after, .bootstrap-datetimepicker-widget table th.prev::after, .bootstrap-datetimepicker-widget table th.next::after {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
border: 0; }
|
||||||
|
|
||||||
|
.bootstrap-datetimepicker-widget {
|
||||||
|
list-style: none; }
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu {
|
||||||
|
margin: 2px 0;
|
||||||
|
padding: 4px;
|
||||||
|
width: 19em; }
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
|
||||||
|
width: 38em; } }
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
|
||||||
|
width: 38em; } }
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
|
||||||
|
width: 38em; } }
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu:before, .bootstrap-datetimepicker-widget.dropdown-menu:after {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute; }
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before {
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-bottom: 7px solid #ccc;
|
||||||
|
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||||
|
top: -7px;
|
||||||
|
left: 7px; }
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after {
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid white;
|
||||||
|
top: -6px;
|
||||||
|
left: 8px; }
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu.top:before {
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-top: 7px solid #ccc;
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.2);
|
||||||
|
bottom: -7px;
|
||||||
|
left: 6px; }
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu.top:after {
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-top: 6px solid white;
|
||||||
|
bottom: -6px;
|
||||||
|
left: 7px; }
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before {
|
||||||
|
left: auto;
|
||||||
|
right: 6px; }
|
||||||
|
.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after {
|
||||||
|
left: auto;
|
||||||
|
right: 7px; }
|
||||||
|
.bootstrap-datetimepicker-widget .list-unstyled {
|
||||||
|
margin: 0; }
|
||||||
|
.bootstrap-datetimepicker-widget a[data-action] {
|
||||||
|
padding: 6px 0; }
|
||||||
|
.bootstrap-datetimepicker-widget a[data-action]:active {
|
||||||
|
box-shadow: none; }
|
||||||
|
.bootstrap-datetimepicker-widget .timepicker-hour, .bootstrap-datetimepicker-widget .timepicker-minute, .bootstrap-datetimepicker-widget .timepicker-second {
|
||||||
|
width: 54px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin: 0; }
|
||||||
|
.bootstrap-datetimepicker-widget button[data-action] {
|
||||||
|
padding: 6px; }
|
||||||
|
.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after {
|
||||||
|
content: "Increment Hours"; }
|
||||||
|
.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after {
|
||||||
|
content: "Increment Minutes"; }
|
||||||
|
.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after {
|
||||||
|
content: "Decrement Hours"; }
|
||||||
|
.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after {
|
||||||
|
content: "Decrement Minutes"; }
|
||||||
|
.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after {
|
||||||
|
content: "Show Hours"; }
|
||||||
|
.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after {
|
||||||
|
content: "Show Minutes"; }
|
||||||
|
.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after {
|
||||||
|
content: "Toggle AM/PM"; }
|
||||||
|
.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after {
|
||||||
|
content: "Clear the picker"; }
|
||||||
|
.bootstrap-datetimepicker-widget .btn[data-action="today"]::after {
|
||||||
|
content: "Set the date to today"; }
|
||||||
|
.bootstrap-datetimepicker-widget .picker-switch {
|
||||||
|
text-align: center; }
|
||||||
|
.bootstrap-datetimepicker-widget .picker-switch::after {
|
||||||
|
content: "Toggle Date and Time Screens"; }
|
||||||
|
.bootstrap-datetimepicker-widget .picker-switch td {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
line-height: inherit; }
|
||||||
|
.bootstrap-datetimepicker-widget .picker-switch td span {
|
||||||
|
line-height: 2.5;
|
||||||
|
height: 2.5em;
|
||||||
|
width: 100%; }
|
||||||
|
.bootstrap-datetimepicker-widget table {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0; }
|
||||||
|
.bootstrap-datetimepicker-widget table td,
|
||||||
|
.bootstrap-datetimepicker-widget table th {
|
||||||
|
text-align: center;
|
||||||
|
border-radius: #333333; }
|
||||||
|
.bootstrap-datetimepicker-widget table th {
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
width: 20px; }
|
||||||
|
.bootstrap-datetimepicker-widget table th.picker-switch {
|
||||||
|
width: 145px; }
|
||||||
|
.bootstrap-datetimepicker-widget table th.disabled, .bootstrap-datetimepicker-widget table th.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: gray;
|
||||||
|
cursor: not-allowed; }
|
||||||
|
.bootstrap-datetimepicker-widget table th.prev::after {
|
||||||
|
content: "Previous Month"; }
|
||||||
|
.bootstrap-datetimepicker-widget table th.next::after {
|
||||||
|
content: "Next Month"; }
|
||||||
|
.bootstrap-datetimepicker-widget table thead tr:first-child th {
|
||||||
|
cursor: pointer; }
|
||||||
|
.bootstrap-datetimepicker-widget table thead tr:first-child th:hover {
|
||||||
|
background: gray; }
|
||||||
|
.bootstrap-datetimepicker-widget table td {
|
||||||
|
height: 54px;
|
||||||
|
line-height: 54px;
|
||||||
|
width: 54px; }
|
||||||
|
.bootstrap-datetimepicker-widget table td.cw {
|
||||||
|
font-size: .8em;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: gray; }
|
||||||
|
.bootstrap-datetimepicker-widget table td.day {
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
width: 20px; }
|
||||||
|
.bootstrap-datetimepicker-widget table td.day:hover, .bootstrap-datetimepicker-widget table td.hour:hover, .bootstrap-datetimepicker-widget table td.minute:hover, .bootstrap-datetimepicker-widget table td.second:hover {
|
||||||
|
background: gray;
|
||||||
|
cursor: pointer; }
|
||||||
|
.bootstrap-datetimepicker-widget table td.old, .bootstrap-datetimepicker-widget table td.new {
|
||||||
|
color: gray; }
|
||||||
|
.bootstrap-datetimepicker-widget table td.today {
|
||||||
|
position: relative; }
|
||||||
|
.bootstrap-datetimepicker-widget table td.today:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border: 0 0 7px 7px solid transparent;
|
||||||
|
border-bottom-color: #df691a;
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.2);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 4px;
|
||||||
|
right: 4px; }
|
||||||
|
.bootstrap-datetimepicker-widget table td.active, .bootstrap-datetimepicker-widget table td.active:hover {
|
||||||
|
background-color: #df691a;
|
||||||
|
color: #ff761b;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); }
|
||||||
|
.bootstrap-datetimepicker-widget table td.active.today:before {
|
||||||
|
border-bottom-color: #fff; }
|
||||||
|
.bootstrap-datetimepicker-widget table td.disabled, .bootstrap-datetimepicker-widget table td.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: gray;
|
||||||
|
cursor: not-allowed; }
|
||||||
|
.bootstrap-datetimepicker-widget table td span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 54px;
|
||||||
|
height: 54px;
|
||||||
|
line-height: 54px;
|
||||||
|
margin: 2px 1.5px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: #333333; }
|
||||||
|
.bootstrap-datetimepicker-widget table td span:hover {
|
||||||
|
background: gray; }
|
||||||
|
.bootstrap-datetimepicker-widget table td span.active {
|
||||||
|
background-color: #df691a;
|
||||||
|
color: #ff761b;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); }
|
||||||
|
.bootstrap-datetimepicker-widget table td span.old {
|
||||||
|
color: gray; }
|
||||||
|
.bootstrap-datetimepicker-widget table td span.disabled, .bootstrap-datetimepicker-widget table td span.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: gray;
|
||||||
|
cursor: not-allowed; }
|
||||||
|
.bootstrap-datetimepicker-widget.usetwentyfour td.hour {
|
||||||
|
height: 27px;
|
||||||
|
line-height: 27px; }
|
||||||
|
|
||||||
|
.input-group.date .input-group-addon {
|
||||||
|
cursor: pointer; }
|
||||||
|
|
6
PlexRequests.UI/Content/datepicker.min.css
vendored
Normal file
6
PlexRequests.UI/Content/datepicker.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
353
PlexRequests.UI/Content/datepicker.scss
Normal file
353
PlexRequests.UI/Content/datepicker.scss
Normal file
|
@ -0,0 +1,353 @@
|
||||||
|
/*!
|
||||||
|
* Datetimepicker for Bootstrap 3
|
||||||
|
* ! version : 4.7.14
|
||||||
|
* https://github.com/Eonasdan/bootstrap-datetimepicker/
|
||||||
|
*/
|
||||||
|
$bs-datetimepicker-timepicker-font-size: 1.2em !default;
|
||||||
|
$bs-datetimepicker-active-bg: #df691a !default;
|
||||||
|
$bs-datetimepicker-active-color: #ff761b !default;
|
||||||
|
$bs-datetimepicker-border-radius: #333333 !default;
|
||||||
|
$bs-datetimepicker-btn-hover-bg: gray !default;
|
||||||
|
$bs-datetimepicker-disabled-color: gray !default;
|
||||||
|
$bs-datetimepicker-alternate-color: gray !default;
|
||||||
|
$bs-datetimepicker-secondary-border-color: #ccc !default;
|
||||||
|
$bs-datetimepicker-secondary-border-color-rgba: rgba(0, 0, 0, 0.2) !default;
|
||||||
|
$bs-datetimepicker-primary-border-color: white !default;
|
||||||
|
$bs-datetimepicker-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25) !default;
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0,0,0,0);
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-datetimepicker-widget {
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
&.dropdown-menu {
|
||||||
|
margin: 2px 0;
|
||||||
|
padding: 4px;
|
||||||
|
width: 19em;
|
||||||
|
|
||||||
|
&.timepicker-sbs {
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
width: 38em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
width: 38em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
width: 38em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before, &:after {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bottom {
|
||||||
|
&:before {
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-bottom: 7px solid $bs-datetimepicker-secondary-border-color;
|
||||||
|
border-bottom-color: $bs-datetimepicker-secondary-border-color-rgba;
|
||||||
|
top: -7px;
|
||||||
|
left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid $bs-datetimepicker-primary-border-color;
|
||||||
|
top: -6px;
|
||||||
|
left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.top {
|
||||||
|
&:before {
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-top: 7px solid $bs-datetimepicker-secondary-border-color;
|
||||||
|
border-top-color: $bs-datetimepicker-secondary-border-color-rgba;
|
||||||
|
bottom: -7px;
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-top: 6px solid $bs-datetimepicker-primary-border-color;
|
||||||
|
bottom: -6px;
|
||||||
|
left: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pull-right {
|
||||||
|
&:before {
|
||||||
|
left: auto;
|
||||||
|
right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
left: auto;
|
||||||
|
right: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-unstyled {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[data-action] {
|
||||||
|
padding: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[data-action]:active {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timepicker-hour, .timepicker-minute, .timepicker-second {
|
||||||
|
width: 54px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: $bs-datetimepicker-timepicker-font-size;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button[data-action] {
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn[data-action="incrementHours"]::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Increment Hours";
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn[data-action="incrementMinutes"]::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Increment Minutes";
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn[data-action="decrementHours"]::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Decrement Hours";
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn[data-action="decrementMinutes"]::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Decrement Minutes";
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn[data-action="showHours"]::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Show Hours";
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn[data-action="showMinutes"]::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Show Minutes";
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn[data-action="togglePeriod"]::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Toggle AM/PM";
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn[data-action="clear"]::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Clear the picker";
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn[data-action="today"]::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Set the date to today";
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-switch {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Toggle Date and Time Screens";
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
line-height: inherit;
|
||||||
|
|
||||||
|
span {
|
||||||
|
line-height: 2.5;
|
||||||
|
height: 2.5em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
|
||||||
|
& td,
|
||||||
|
& th {
|
||||||
|
text-align: center;
|
||||||
|
border-radius: $bs-datetimepicker-border-radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
& th {
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
|
||||||
|
&.picker-switch {
|
||||||
|
width: 145px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled,
|
||||||
|
&.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: $bs-datetimepicker-disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.prev::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Previous Month";
|
||||||
|
}
|
||||||
|
|
||||||
|
&.next::after {
|
||||||
|
@extend .sr-only;
|
||||||
|
content: "Next Month";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& thead tr:first-child th {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $bs-datetimepicker-btn-hover-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& td {
|
||||||
|
height: 54px;
|
||||||
|
line-height: 54px;
|
||||||
|
width: 54px;
|
||||||
|
|
||||||
|
&.cw {
|
||||||
|
font-size: .8em;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: $bs-datetimepicker-alternate-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.day {
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.day:hover,
|
||||||
|
&.hour:hover,
|
||||||
|
&.minute:hover,
|
||||||
|
&.second:hover {
|
||||||
|
background: $bs-datetimepicker-btn-hover-bg;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.old,
|
||||||
|
&.new {
|
||||||
|
color: $bs-datetimepicker-alternate-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.today {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border: 0 0 7px 7px solid transparent;
|
||||||
|
border-bottom-color: $bs-datetimepicker-active-bg;
|
||||||
|
border-top-color: $bs-datetimepicker-secondary-border-color-rgba;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 4px;
|
||||||
|
right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active,
|
||||||
|
&.active:hover {
|
||||||
|
background-color: $bs-datetimepicker-active-bg;
|
||||||
|
color: $bs-datetimepicker-active-color;
|
||||||
|
text-shadow: $bs-datetimepicker-text-shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active.today:before {
|
||||||
|
border-bottom-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled,
|
||||||
|
&.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: $bs-datetimepicker-disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 54px;
|
||||||
|
height: 54px;
|
||||||
|
line-height: 54px;
|
||||||
|
margin: 2px 1.5px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: $bs-datetimepicker-border-radius;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $bs-datetimepicker-btn-hover-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: $bs-datetimepicker-active-bg;
|
||||||
|
color: $bs-datetimepicker-active-color;
|
||||||
|
text-shadow: $bs-datetimepicker-text-shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.old {
|
||||||
|
color: $bs-datetimepicker-alternate-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled,
|
||||||
|
&.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: $bs-datetimepicker-disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.usetwentyfour {
|
||||||
|
td.hour {
|
||||||
|
height: 27px;
|
||||||
|
line-height: 27px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group.date {
|
||||||
|
& .input-group-addon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ namespace PlexRequests.UI.Helpers
|
||||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/awesome-bootstrap-checkbox.css\" type=\"text/css\"/>");
|
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/awesome-bootstrap-checkbox.css\" type=\"text/css\"/>");
|
||||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/base.css\" type=\"text/css\"/>");
|
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/base.css\" type=\"text/css\"/>");
|
||||||
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/Themes/{settings.ThemeName}\" type=\"text/css\"/>");
|
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/Themes/{settings.ThemeName}\" type=\"text/css\"/>");
|
||||||
|
sb.AppendLine($"<link rel=\"stylesheet\" href=\"{content}/Content/datepicker.min.css\" type=\"text/css\"/>");
|
||||||
|
|
||||||
sb.AppendLine($"<script src=\"{content}/Content/jquery-2.2.1.min.js\"></script>");
|
sb.AppendLine($"<script src=\"{content}/Content/jquery-2.2.1.min.js\"></script>");
|
||||||
sb.AppendLine($"<script src=\"{content}/Content/handlebars.min.js\"></script>");
|
sb.AppendLine($"<script src=\"{content}/Content/handlebars.min.js\"></script>");
|
||||||
|
@ -75,6 +76,7 @@ namespace PlexRequests.UI.Helpers
|
||||||
sb.AppendLine($"<script src=\"{content}/Content/pace.min.js\"></script>");
|
sb.AppendLine($"<script src=\"{content}/Content/pace.min.js\"></script>");
|
||||||
sb.AppendLine($"<script src=\"{content}/Content/jquery.mixitup.js\"></script>");
|
sb.AppendLine($"<script src=\"{content}/Content/jquery.mixitup.js\"></script>");
|
||||||
sb.AppendLine($"<script src=\"{content}/Content/moment.min.js\"></script>");
|
sb.AppendLine($"<script src=\"{content}/Content/moment.min.js\"></script>");
|
||||||
|
sb.AppendLine($"<script src=\"{content}/Content/bootstrap-datetimepicker.min.js\"></script>");
|
||||||
|
|
||||||
|
|
||||||
return helper.Raw(sb.ToString());
|
return helper.Raw(sb.ToString());
|
||||||
|
|
|
@ -55,6 +55,7 @@ using PlexRequests.UI.Helpers;
|
||||||
using PlexRequests.UI.Models;
|
using PlexRequests.UI.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Nancy.Json;
|
using Nancy.Json;
|
||||||
using Nancy.Security;
|
using Nancy.Security;
|
||||||
|
@ -83,6 +84,7 @@ namespace PlexRequests.UI.Modules
|
||||||
private INotificationService NotificationService { get; }
|
private INotificationService NotificationService { get; }
|
||||||
private ICacheProvider Cache { get; }
|
private ICacheProvider Cache { get; }
|
||||||
private ISettingsService<SlackNotificationSettings> SlackSettings { get; }
|
private ISettingsService<SlackNotificationSettings> SlackSettings { get; }
|
||||||
|
private ISettingsService<LandingPageSettings> LandingSettings { get; }
|
||||||
private ISlackApi SlackApi { get; }
|
private ISlackApi SlackApi { get; }
|
||||||
|
|
||||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
@ -105,7 +107,7 @@ namespace PlexRequests.UI.Modules
|
||||||
ISettingsService<HeadphonesSettings> headphones,
|
ISettingsService<HeadphonesSettings> headphones,
|
||||||
ISettingsService<LogSettings> logs,
|
ISettingsService<LogSettings> logs,
|
||||||
ICacheProvider cache, ISettingsService<SlackNotificationSettings> slackSettings,
|
ICacheProvider cache, ISettingsService<SlackNotificationSettings> slackSettings,
|
||||||
ISlackApi slackApi) : base("admin", prService)
|
ISlackApi slackApi, ISettingsService<LandingPageSettings> lp) : base("admin", prService)
|
||||||
{
|
{
|
||||||
PrService = prService;
|
PrService = prService;
|
||||||
CpService = cpService;
|
CpService = cpService;
|
||||||
|
@ -128,6 +130,7 @@ namespace PlexRequests.UI.Modules
|
||||||
Cache = cache;
|
Cache = cache;
|
||||||
SlackSettings = slackSettings;
|
SlackSettings = slackSettings;
|
||||||
SlackApi = slackApi;
|
SlackApi = slackApi;
|
||||||
|
LandingSettings = lp;
|
||||||
|
|
||||||
this.RequiresClaims(UserClaims.Admin);
|
this.RequiresClaims(UserClaims.Admin);
|
||||||
|
|
||||||
|
@ -186,6 +189,9 @@ namespace PlexRequests.UI.Modules
|
||||||
|
|
||||||
Get["/slacknotification"] = _ => SlackNotifications();
|
Get["/slacknotification"] = _ => SlackNotifications();
|
||||||
Post["/slacknotification"] = _ => SaveSlackNotifications();
|
Post["/slacknotification"] = _ => SaveSlackNotifications();
|
||||||
|
|
||||||
|
Get["/landingpage", true] = async (x,ct) => await LandingPage();
|
||||||
|
Post["/landingpage"] = _ => SaveSlackNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Negotiator Authentication()
|
private Negotiator Authentication()
|
||||||
|
@ -806,5 +812,12 @@ namespace PlexRequests.UI.Modules
|
||||||
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Slack Notifications!" }
|
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Slack Notifications!" }
|
||||||
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<Negotiator> LandingPage()
|
||||||
|
{
|
||||||
|
var settings = await LandingSettings.GetSettingsAsync();
|
||||||
|
|
||||||
|
return View["LandingPage", settings];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
41
PlexRequests.UI/Modules/LandingPageModule.cs
Normal file
41
PlexRequests.UI/Modules/LandingPageModule.cs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2016 Jamie Rees
|
||||||
|
// File: LandingPageModule.cs
|
||||||
|
// Created By: Jamie Rees
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
// ************************************************************************/
|
||||||
|
#endregion
|
||||||
|
using PlexRequests.Core;
|
||||||
|
using PlexRequests.Core.SettingModels;
|
||||||
|
|
||||||
|
namespace PlexRequests.UI.Modules
|
||||||
|
{
|
||||||
|
public class LandingPageModule : BaseModule
|
||||||
|
{
|
||||||
|
public LandingPageModule(ISettingsService<PlexRequestSettings> settingsService, ISettingsService<LandingPageSettings> landing) : base("landing", settingsService)
|
||||||
|
{
|
||||||
|
LandingSettings = landing;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ISettingsService<LandingPageSettings> LandingSettings { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -193,6 +193,7 @@
|
||||||
<Compile Include="Modules\BaseApiModule.cs" />
|
<Compile Include="Modules\BaseApiModule.cs" />
|
||||||
<Compile Include="Modules\BaseModule.cs" />
|
<Compile Include="Modules\BaseModule.cs" />
|
||||||
<Compile Include="Modules\IssuesModule.cs" />
|
<Compile Include="Modules\IssuesModule.cs" />
|
||||||
|
<Compile Include="Modules\LandingPageModule.cs" />
|
||||||
<Compile Include="Modules\UpdateCheckerModule.cs" />
|
<Compile Include="Modules\UpdateCheckerModule.cs" />
|
||||||
<Compile Include="Start\StartupOptions.cs" />
|
<Compile Include="Start\StartupOptions.cs" />
|
||||||
<Compile Include="Start\UpdateValue.cs" />
|
<Compile Include="Start\UpdateValue.cs" />
|
||||||
|
@ -243,6 +244,13 @@
|
||||||
<Compile Include="Startup.cs" />
|
<Compile Include="Startup.cs" />
|
||||||
<Compile Include="Validators\PlexRequestsValidator.cs" />
|
<Compile Include="Validators\PlexRequestsValidator.cs" />
|
||||||
<Compile Include="Modules\UserManagementModule.cs" />
|
<Compile Include="Modules\UserManagementModule.cs" />
|
||||||
|
<Content Include="Content\datepicker.css">
|
||||||
|
<DependentUpon>datepicker.scss</DependentUpon>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Content\datepicker.min.css">
|
||||||
|
<DependentUpon>datepicker.css</DependentUpon>
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="Content\issue-details.js">
|
<Content Include="Content\issue-details.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -319,6 +327,13 @@
|
||||||
<DependentUpon>plex.css</DependentUpon>
|
<DependentUpon>plex.css</DependentUpon>
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Content\bootstrap-datetimepicker.min.js">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Scripts\bootstrap-datetimepicker.js" />
|
||||||
|
<Content Include="Scripts\bootstrap-datetimepicker.min.js" />
|
||||||
|
<Content Include="Scripts\bootstrap.js" />
|
||||||
|
<Content Include="Scripts\bootstrap.min.js" />
|
||||||
<Content Include="Views\ApiDocs\index.html">
|
<Content Include="Views\ApiDocs\index.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -400,10 +415,11 @@
|
||||||
<None Include="compilerconfig.json.defaults">
|
<None Include="compilerconfig.json.defaults">
|
||||||
<DependentUpon>compilerconfig.json</DependentUpon>
|
<DependentUpon>compilerconfig.json</DependentUpon>
|
||||||
</None>
|
</None>
|
||||||
<None Include="Content\awesome-bootstrap-checkbox.scss">
|
<None Include="Content\datepicker.scss">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="Content\base.scss" />
|
<None Include="Content\base.scss" />
|
||||||
|
<None Include="Content\bootstrap-datetimepicker-build.less" />
|
||||||
<None Include="Content\Themes\original.scss" />
|
<None Include="Content\Themes\original.scss" />
|
||||||
<None Include="Content\Themes\plex.scss" />
|
<None Include="Content\Themes\plex.scss" />
|
||||||
<Content Include="Content\pace.min.js">
|
<Content Include="Content\pace.min.js">
|
||||||
|
@ -524,6 +540,9 @@
|
||||||
<Content Include="Views\Issues\Details.cshtml">
|
<Content Include="Views\Issues\Details.cshtml">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Views\Admin\LandingPage.cshtml">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<None Include="Web.Debug.config">
|
<None Include="Web.Debug.config">
|
||||||
<DependentUpon>web.config</DependentUpon>
|
<DependentUpon>web.config</DependentUpon>
|
||||||
</None>
|
</None>
|
||||||
|
|
2485
PlexRequests.UI/Scripts/bootstrap-datetimepicker.js
vendored
Normal file
2485
PlexRequests.UI/Scripts/bootstrap-datetimepicker.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
9
PlexRequests.UI/Scripts/bootstrap-datetimepicker.min.js
vendored
Normal file
9
PlexRequests.UI/Scripts/bootstrap-datetimepicker.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2363
PlexRequests.UI/Scripts/bootstrap.js
vendored
Normal file
2363
PlexRequests.UI/Scripts/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
7
PlexRequests.UI/Scripts/bootstrap.min.js
vendored
Normal file
7
PlexRequests.UI/Scripts/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
146
PlexRequests.UI/Views/Admin/LandingPage.cshtml
Normal file
146
PlexRequests.UI/Views/Admin/LandingPage.cshtml
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
@using PlexRequests.UI.Helpers
|
||||||
|
@Html.Partial("_Sidebar")
|
||||||
|
@{
|
||||||
|
var baseUrl = Html.GetBaseUrl();
|
||||||
|
var formAction = "/admin";
|
||||||
|
if (!string.IsNullOrEmpty(baseUrl.ToHtmlString()))
|
||||||
|
{
|
||||||
|
formAction = "/" + baseUrl.ToHtmlString() + formAction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<div class="col-sm-8 col-sm-push-1">
|
||||||
|
<form class="form-horizontal" method="POST" id="mainForm">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Landing Page Settings</legend>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
|
||||||
|
@if (Model.Enabled)
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Enabled" name="Enabled" checked="checked"><label for="Enabled">Enabled</label>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="Enabled" name="Enabled"><label for="Enabled">Enabled</label>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<small>If enabled then all users will be redirected to the landing page instead of the login page.</small>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
|
||||||
|
@if (Model.NoticeEnable)
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="NoticeEnable" name="NoticeEnable" checked="checked"><label for="NoticeEnable">Enable a notice</label>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="NoticeEnable" name="NoticeEnable"><label for="NoticeEnable">Enable a notice</label>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="form-group">Notice Message</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control-custom form-control " id="NoticeMessage" name="NoticeMessage" placeholder="e.g. Plex will be down for maintaince" value="@Model.NoticeMessage">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
|
||||||
|
@if (Model.EnabledNoticeTime)
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="EnabledNoticeTime" name="EnabledNoticeTime" checked="checked"><label for="EnabledNoticeTime">Enable a time limit for the notices</label>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="checkbox" id="EnabledNoticeTime" name="EnabledNoticeTime"><label for="EnabledNoticeTime">Enable a time limit for the notices</label>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class='input-group date' id='datetimepicker6'>
|
||||||
|
<input type='text' class="form-control" />
|
||||||
|
<span class="input-group-addon">
|
||||||
|
<span class="glyphicon glyphicon-calendar"></span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class='input-group date' id='datetimepicker7'>
|
||||||
|
<input type='text' class="form-control"/>
|
||||||
|
<span class="input-group-addon">
|
||||||
|
<span class="glyphicon glyphicon-calendar"></span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button type="submit" id="save" class="btn btn-primary-outline">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
$('#save').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var theme = $("#themes option:selected").val();
|
||||||
|
var $form = $("#mainForm");
|
||||||
|
|
||||||
|
var data = $form.serialize();
|
||||||
|
data = data + "&themeName=" + theme;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: $form.prop("method"),
|
||||||
|
data: data,
|
||||||
|
url: $form.prop("action"),
|
||||||
|
dataType: "json",
|
||||||
|
success: function (response) {
|
||||||
|
if (response.result === true) {
|
||||||
|
generateNotify("Success!", "success");
|
||||||
|
} else {
|
||||||
|
generateNotify(response.message, "warning");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (e) {
|
||||||
|
console.log(e);
|
||||||
|
generateNotify("Something went wrong!", "danger");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$('#datetimepicker6').datetimepicker({
|
||||||
|
dayViewHeaderFormat: 'MMMM YYYY'
|
||||||
|
});
|
||||||
|
$('#datetimepicker7').datetimepicker({
|
||||||
|
useCurrent: false //Important! See issue #1075
|
||||||
|
});
|
||||||
|
$("#datetimepicker6").on("dp.change", function (e) {
|
||||||
|
$('#datetimepicker7').data("DateTimePicker").minDate(e.date);
|
||||||
|
});
|
||||||
|
$("#datetimepicker7").on("dp.change", function (e) {
|
||||||
|
$('#datetimepicker6').data("DateTimePicker").maxDate(e.date);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -2,6 +2,7 @@
|
||||||
<div class="col-lg-3 col-md-3 col-sm-4">
|
<div class="col-lg-3 col-md-3 col-sm-4">
|
||||||
<div class="list-group table-of-contents">
|
<div class="list-group table-of-contents">
|
||||||
@Html.GetSidebarUrl(Context, "/admin", "Plex Request")
|
@Html.GetSidebarUrl(Context, "/admin", "Plex Request")
|
||||||
|
@Html.GetSidebarUrl(Context, "/admin/landingpage", "Landing Page")
|
||||||
@Html.GetSidebarUrl(Context, "/admin/authentication", "Authentication")
|
@Html.GetSidebarUrl(Context, "/admin/authentication", "Authentication")
|
||||||
@Html.GetSidebarUrl(Context, "/admin/plex", "Plex")
|
@Html.GetSidebarUrl(Context, "/admin/plex", "Plex")
|
||||||
@Html.GetSidebarUrl(Context, "/admin/couchpotato", "CouchPotato")
|
@Html.GetSidebarUrl(Context, "/admin/couchpotato", "CouchPotato")
|
||||||
|
|
|
@ -26,5 +26,13 @@
|
||||||
{
|
{
|
||||||
"outputFile": "Content/Themes/original.css",
|
"outputFile": "Content/Themes/original.css",
|
||||||
"inputFile": "Content/Themes/original.scss"
|
"inputFile": "Content/Themes/original.scss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"outputFile": "Content/_bootstrap-datetimepicker.css",
|
||||||
|
"inputFile": "Content/_bootstrap-datetimepicker.less"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"outputFile": "Content/datepicker.css",
|
||||||
|
"inputFile": "Content/datepicker.scss"
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -1,16 +1,20 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
|
<package id="bootstrap.less" version="3.3.5" targetFramework="net45" />
|
||||||
|
<package id="Bootstrap.v3.Datetimepicker" version="4.15.35.1" targetFramework="net45" />
|
||||||
<package id="CommandLineParser" version="2.0.275-beta" targetFramework="net45" />
|
<package id="CommandLineParser" version="2.0.275-beta" targetFramework="net45" />
|
||||||
<package id="Common.Logging" version="3.0.0" targetFramework="net45" />
|
<package id="Common.Logging" version="3.0.0" targetFramework="net45" />
|
||||||
<package id="Common.Logging.Core" version="3.0.0" targetFramework="net45" />
|
<package id="Common.Logging.Core" version="3.0.0" targetFramework="net45" />
|
||||||
<package id="Dapper" version="1.42" targetFramework="net45" />
|
<package id="Dapper" version="1.42" targetFramework="net45" />
|
||||||
<package id="FluentValidation" version="6.2.1.0" targetFramework="net45" />
|
<package id="FluentValidation" version="6.2.1.0" targetFramework="net45" />
|
||||||
|
<package id="jQuery" version="1.9.1" targetFramework="net45" />
|
||||||
<package id="MarkdownSharp" version="1.13.0.0" targetFramework="net45" />
|
<package id="MarkdownSharp" version="1.13.0.0" targetFramework="net45" />
|
||||||
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net45" />
|
<package id="Microsoft.AspNet.Razor" version="2.0.30506.0" targetFramework="net45" />
|
||||||
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
|
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
|
||||||
<package id="Microsoft.Owin.Host.HttpListener" version="3.0.1" targetFramework="net45" />
|
<package id="Microsoft.Owin.Host.HttpListener" version="3.0.1" targetFramework="net45" />
|
||||||
<package id="Microsoft.Owin.Host.SystemWeb" version="3.0.0" targetFramework="net45" />
|
<package id="Microsoft.Owin.Host.SystemWeb" version="3.0.0" targetFramework="net45" />
|
||||||
<package id="Microsoft.Owin.Hosting" version="3.0.1" targetFramework="net45" />
|
<package id="Microsoft.Owin.Hosting" version="3.0.1" targetFramework="net45" />
|
||||||
|
<package id="Moment.js" version="2.9.0" targetFramework="net45" />
|
||||||
<package id="Mono.Posix" version="4.0.0.0" targetFramework="net45" />
|
<package id="Mono.Posix" version="4.0.0.0" targetFramework="net45" />
|
||||||
<package id="Nancy" version="1.4.3" targetFramework="net45" />
|
<package id="Nancy" version="1.4.3" targetFramework="net45" />
|
||||||
<package id="Nancy.Authentication.Basic" version="1.4.1" targetFramework="net45" />
|
<package id="Nancy.Authentication.Basic" version="1.4.1" targetFramework="net45" />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue