Cleanup
This commit is contained in:
parent
527be316ff
commit
7ee7ebc4b3
@ -17,7 +17,6 @@ namespace Squirrowse.Client
|
||||
return Host.CreateDefaultBuilder(args)
|
||||
.ConfigureServices((hostContext, services) =>
|
||||
{
|
||||
|
||||
services.AddHostedService<Worker>();
|
||||
services.AddSingleton<IConnectionManager>(x =>
|
||||
new ConnectionManager("http://localhost", 5000)); //keep as transient for now
|
||||
|
@ -10,12 +10,13 @@ namespace Squirrowse.Client.Service
|
||||
{
|
||||
public class ActionDispatcher : IActionDispatcher
|
||||
{
|
||||
private readonly ICameraService camera;
|
||||
private readonly IConnectionManager connectionManager;
|
||||
private readonly ILogger<ActionDispatcher> logger;
|
||||
private readonly HubConnection session;
|
||||
private readonly ICameraService camera;
|
||||
|
||||
public ActionDispatcher(ILogger<ActionDispatcher> logger, IConnectionManager connectionManager,ICameraService camera)
|
||||
public ActionDispatcher(ILogger<ActionDispatcher> logger, IConnectionManager connectionManager,
|
||||
ICameraService camera)
|
||||
{
|
||||
this.connectionManager = connectionManager;
|
||||
this.logger = logger;
|
||||
|
@ -23,12 +23,7 @@ namespace Squirrowse.Client
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
await _connectionManager.InitConnection(ConnectionType.Client);
|
||||
}
|
||||
|
||||
|
||||
for (var i = 0; i < 100; i++) await _connectionManager.InitConnection(ConnectionType.Client);
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
|
@ -9,7 +9,7 @@ namespace Squirrowse.Core
|
||||
public static IServiceCollection AddCoreModule(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
|
||||
services.AddSingleton<IConnectionManager>(x =>
|
||||
services.AddSingleton<IConnectionManager, ConnectionManager>(x =>
|
||||
new ConnectionManager("http://localhost", 5000));
|
||||
return services;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
{
|
||||
ConnectionId = connectionId;
|
||||
AgentName = agentName;
|
||||
this.UserType = userType;
|
||||
UserType = userType;
|
||||
}
|
||||
|
||||
public string ConnectionId { get; set; }
|
||||
|
@ -31,8 +31,7 @@ namespace Squirrowse.Core.Services
|
||||
{
|
||||
if (_connection.State == HubConnectionState.Connected) return;
|
||||
await _connection.StartAsync();
|
||||
// await RegisterOnHub(type);
|
||||
await SpamHub(type);
|
||||
await RegisterOnHub(type);
|
||||
Connected = true;
|
||||
}
|
||||
|
||||
@ -48,15 +47,5 @@ namespace Squirrowse.Core.Services
|
||||
{
|
||||
await _connection.SendAsync("AddUser", Environment.UserName, type);
|
||||
}
|
||||
#warning debug
|
||||
private async Task SpamHub(ConnectionType type)
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
await _connection.SendAsync("AddUser", Environment.UserName + $"{DateTime.Now}", type);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Squirrowse.Core.Models;
|
||||
|
||||
|
@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenCvSharp;
|
||||
using Squirrowse.Core.Models;
|
||||
using Squirrowse.Core.Services;
|
||||
|
||||
namespace Squirrowse.Service.Hubs
|
||||
{
|
||||
@ -25,7 +22,6 @@ namespace Squirrowse.Service.Hubs
|
||||
{
|
||||
await manager.AddUser(Context.ConnectionId, UserName, type);
|
||||
logger.LogInformation($"{nameof(AddUser)}: {UserName} of {type}");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -71,9 +67,7 @@ namespace Squirrowse.Service.Hubs
|
||||
public async Task UploadByteStream(IAsyncEnumerable<byte[]> stream)
|
||||
{
|
||||
foreach (var user in manager.getServerSideUsers())
|
||||
{
|
||||
await Clients.Client(user.ConnectionId).SendAsync("RecData", stream);
|
||||
}
|
||||
await foreach (var frame in stream)
|
||||
{
|
||||
logger.LogInformation($"Got frame size: {frame.Length} ");
|
||||
@ -87,40 +81,16 @@ namespace Squirrowse.Service.Hubs
|
||||
if (t == ConnectionType.Server) return manager.getServerSideUsers();
|
||||
throw new Exception("not found");
|
||||
}
|
||||
#warning DEBUG
|
||||
public async Task<string> GetListOfTypeUserString()
|
||||
{
|
||||
string t = "";
|
||||
var tasdf=manager.getClientSideUsers();
|
||||
foreach (var h in tasdf)
|
||||
{
|
||||
t +=h.AgentName;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
#warning DEBUG
|
||||
public async Task<User> Getasuser() => manager.getClientSideUsers().FirstOrDefault();
|
||||
#warning Debug
|
||||
public async Task<List<User>> GetListOfTypeUserE(ConnectionType t)
|
||||
{
|
||||
if (t == ConnectionType.Client) return manager.getClientSideUsers().ToList();
|
||||
if (t == ConnectionType.Server) return manager.getServerSideUsers().ToList();
|
||||
throw new Exception("not found");
|
||||
}
|
||||
#warning debug
|
||||
public async IAsyncEnumerable<User> GetListOfTypeUserAsync(ConnectionType t)
|
||||
{
|
||||
var client = manager.getClientSideUsers();
|
||||
foreach (var va in client)
|
||||
{
|
||||
await Task.Delay(500);
|
||||
yield return va;
|
||||
}
|
||||
}
|
||||
public async Task<IEnumerable<User>> GetAllUsers()
|
||||
{
|
||||
return manager.getAllUsers();
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<User> GetListOfTypeUserAsync(ConnectionType t)
|
||||
{
|
||||
var client = await GetListOfTypeUser(t);
|
||||
foreach (var va in client) yield return va;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ namespace Squirrowse.Service.Hubs
|
||||
{
|
||||
public class StreamManager : IStreamManager
|
||||
{
|
||||
private List<User> _users = new List<User>(); //temporary
|
||||
private readonly List<User> _users = new List<User>(); //temporary
|
||||
|
||||
public Task AddUser(string connectionId, string userName, ConnectionType type)
|
||||
{
|
||||
@ -31,10 +31,12 @@ namespace Squirrowse.Service.Hubs
|
||||
{
|
||||
return _users.Where(user => user.UserType == ConnectionType.Server);
|
||||
}
|
||||
|
||||
public IEnumerable<User> getClientSideUsers()
|
||||
{
|
||||
return _users.Where(user => user.UserType == ConnectionType.Client);
|
||||
}
|
||||
|
||||
public bool CheckUser(string userName)
|
||||
{
|
||||
return _users.Any(user => user.AgentName == userName);
|
||||
|
@ -1,15 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Squirrowse.Web.Data
|
||||
{
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
public int TemperatureC { get; set; }
|
||||
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
|
||||
public string Summary { get; set; }
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Squirrowse.Web.Data
|
||||
{
|
||||
public class WeatherForecastService
|
||||
{
|
||||
private static readonly string[] Summaries = new[]
|
||||
{
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
};
|
||||
|
||||
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
|
||||
{
|
||||
var rng = new Random();
|
||||
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = startDate.AddDays(index),
|
||||
TemperatureC = rng.Next(-20, 55),
|
||||
Summary = Summaries[rng.Next(Summaries.Length)]
|
||||
}).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
@page "/counter"
|
||||
|
||||
<h1>Counter</h1>
|
||||
|
||||
<p>Current count: @currentCount</p>
|
||||
|
||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
||||
|
||||
@code {
|
||||
int currentCount = 0;
|
||||
|
||||
void IncrementCount()
|
||||
{
|
||||
currentCount++;
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
@page "/error"
|
||||
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
@ -1,46 +0,0 @@
|
||||
@page "/fetchdata"
|
||||
|
||||
@using Squirrowse.Web.Data
|
||||
@inject WeatherForecastService ForecastService
|
||||
|
||||
<h1>Weather forecast</h1>
|
||||
|
||||
<p>This component demonstrates fetching data from a service.</p>
|
||||
|
||||
@if (forecasts == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Temp. (C)</th>
|
||||
<th>Temp. (F)</th>
|
||||
<th>Summary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var forecast in forecasts)
|
||||
{
|
||||
<tr>
|
||||
<td>@forecast.Date.ToShortDateString()</td>
|
||||
<td>@forecast.TemperatureC</td>
|
||||
<td>@forecast.TemperatureF</td>
|
||||
<td>@forecast.Summary</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
WeatherForecast[] forecasts;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
|
||||
}
|
||||
}
|
@ -33,25 +33,6 @@
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@*<div class="card-body">
|
||||
<div>
|
||||
<h3 class="badge-primary">
|
||||
@agents.AgentName -> @agents.UserType.ToString()
|
||||
</h3>
|
||||
<div style="padding-top:10px">
|
||||
<button id="ViewCast" disabled="@(IsViewingCastOf(agents.AgentName))" class="btn btn-success btn-sm" @onclick="@(() => OnViewCastClicked(agents.ConnectionId))">
|
||||
View cast
|
||||
</button>
|
||||
|
||||
<button id="StopViewCast" disabled="@(!IsViewingCastOf(agents.AgentName))" class="btn btn-warning btn-sm" @onclick="@(() => OnStopViewCastClicked(agents.ConnectionId))">
|
||||
Stop cast
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>*@
|
||||
|
||||
|
||||
else
|
||||
{
|
||||
<div class="card-body">
|
||||
@ -73,48 +54,25 @@ else
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// agents=new List<User>();
|
||||
await _connection.InitConnection(ConnectionType.Server);
|
||||
connection = await _connection.GetConnection();
|
||||
|
||||
connection.On<IAsyncEnumerable<byte[]>>("RecData", OnStreamDataReceived);
|
||||
//agents = await connection.InvokeAsync<string>("GetListOfTypeUserString");
|
||||
//agents = await connection.InvokeAsync<User>("Getasuser");
|
||||
//agents = await connection.InvokeAsync<IAsyncEnumerable<User>>("GetListOfTypeUserAsync",ConnectionType.Client);
|
||||
await foreach (var dupa in connection.StreamAsync<User>("GetListOfTypeUserAsync", ConnectionType.Client).ConfigureAwait(false))
|
||||
|
||||
await foreach (var user in connection.StreamAsync<User>("GetListOfTypeUserAsync", ConnectionType.Client).ConfigureAwait(false))
|
||||
{
|
||||
agents.Add(dupa);
|
||||
// await Task.Delay(300);
|
||||
agents.Add(user);
|
||||
this.StateHasChanged();
|
||||
}
|
||||
//connection.On<User>("NewUser", NewUser);
|
||||
//connection.On<string>("RemoveScreenCastAgent", RemoveScreenCastAgent);
|
||||
//connection.On<string>("OnStreamDataReceived", OnStreamDataReceived);
|
||||
|
||||
//await connection.StartAsync();
|
||||
}
|
||||
//cannot control enumerator
|
||||
//protected override async Task OnAfterRenderAsync(bool firstRender=true)
|
||||
//{
|
||||
// await foreach (var dupa in connection.StreamAsync<User>("GetListOfTypeUserAsync", ConnectionType.Client))
|
||||
// {
|
||||
// agents.Add(dupa);
|
||||
// await Task.Delay(300);
|
||||
// this.StateHasChanged();
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
bool IsViewingCastOf(string agentName)
|
||||
{
|
||||
return agentName == CurrentViewCastAgent;
|
||||
}
|
||||
|
||||
//void NewUser(User agentName)
|
||||
//{
|
||||
// agents.Add(agentName);
|
||||
// StateHasChanged();
|
||||
//}
|
||||
|
||||
async void OnStreamDataReceived(IAsyncEnumerable<byte[]> streamData)
|
||||
{
|
||||
await foreach (var t in streamData)
|
||||
|
@ -1,13 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Squirrowse.Web
|
||||
{
|
||||
@ -18,11 +10,10 @@ namespace Squirrowse.Web
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
return Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
|
||||
}
|
||||
}
|
||||
}
|
@ -12,16 +12,6 @@
|
||||
<span class="oi oi-home" aria-hidden="true"></span> Home
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="counter">
|
||||
<span class="oi oi-plus" aria-hidden="true"></span> Counter
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="fetchdata">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
|
||||
</NavLink>
|
||||
</li>
|
||||
<li class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="Hub">
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Stream
|
||||
@ -39,4 +29,5 @@
|
||||
{
|
||||
collapseNavMenu = !collapseNavMenu;
|
||||
}
|
||||
|
||||
}
|
@ -14,4 +14,8 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Data\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,16 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Squirrowse.Core;
|
||||
using Squirrowse.Web.Data;
|
||||
|
||||
namespace Squirrowse.Web
|
||||
{
|
||||
@ -32,7 +25,6 @@ namespace Squirrowse.Web
|
||||
services.AddServerSideBlazor().AddHubOptions(x => x.MaximumReceiveMessageSize = 102400000);
|
||||
services.AddCoreModule();
|
||||
services.AddSignalR().AddMessagePackProtocol();
|
||||
services.AddSingleton<WeatherForecastService>();
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
|
@ -1,34 +1,28 @@
|
||||
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
|
||||
|
||||
html, body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
html, body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; }
|
||||
|
||||
a, .btn-link {
|
||||
color: #0366d6;
|
||||
}
|
||||
a, .btn-link { color: #0366d6; }
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
app {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 3.5rem;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
}
|
||||
.main { flex: 1; }
|
||||
|
||||
.main .top-row {
|
||||
background-color: #f7f7f7;
|
||||
@ -36,27 +30,19 @@ app {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.main .top-row > a {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
.main .top-row > a { margin-left: 1.5rem; }
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
|
||||
}
|
||||
.sidebar { background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); }
|
||||
|
||||
.sidebar .top-row {
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
.sidebar .top-row { background-color: rgba(0, 0, 0, 0.4); }
|
||||
|
||||
.sidebar .navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
.sidebar .navbar-brand { font-size: 1.1rem; }
|
||||
|
||||
.sidebar .oi {
|
||||
width: 2rem;
|
||||
font-size: 1.1rem;
|
||||
vertical-align: text-top;
|
||||
top: -2px;
|
||||
vertical-align: text-top;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
@ -64,20 +50,16 @@ app {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
.nav-item:first-of-type { padding-top: 1rem; }
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
.nav-item:last-of-type { padding-bottom: 1rem; }
|
||||
|
||||
.nav-item a {
|
||||
color: #d7d7d7;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
color: #d7d7d7;
|
||||
display: flex;
|
||||
height: 3rem;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
@ -91,42 +73,28 @@ app {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1.1rem;
|
||||
}
|
||||
.content { padding-top: 1.1rem; }
|
||||
|
||||
.navbar-toggler {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.navbar-toggler { background-color: rgba(255, 255, 255, 0.1); }
|
||||
|
||||
.valid.modified:not([type=checkbox]) {
|
||||
outline: 1px solid #26b050;
|
||||
}
|
||||
.valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; }
|
||||
|
||||
.invalid {
|
||||
outline: 1px solid red;
|
||||
}
|
||||
.invalid { outline: 1px solid red; }
|
||||
|
||||
.validation-message {
|
||||
color: red;
|
||||
}
|
||||
.validation-message { color: red; }
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.main .top-row {
|
||||
display: none;
|
||||
}
|
||||
.main .top-row { display: none; }
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
app {
|
||||
flex-direction: row;
|
||||
}
|
||||
app { flex-direction: row; }
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.main .top-row {
|
||||
@ -139,9 +107,7 @@ app {
|
||||
padding-right: 1.5rem !important;
|
||||
}
|
||||
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
.navbar-toggler { display: none; }
|
||||
|
||||
.sidebar .collapse {
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
|
Loading…
Reference in New Issue
Block a user