This commit is contained in:
tidusjar 2016-06-06 14:31:20 +01:00
parent 071daf4ab4
commit 0dd30968d5
22 changed files with 8276 additions and 252 deletions

View file

@ -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" />

View 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; }
}
}

View file

@ -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) =>

View file

@ -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>>();

View file

@ -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;
}
}
}

View 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;
}

File diff suppressed because it is too large Load diff

View 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; }

File diff suppressed because one or more lines are too long

View 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;
}
}

View file

@ -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());

View file

@ -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];
}
} }
} }

View 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; }
}
}

View file

@ -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>

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

2363
PlexRequests.UI/Scripts/bootstrap.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View 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>

View file

@ -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")

View file

@ -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"
} }
] ]

View file

@ -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" />