Merge pull request #1703 from sbwalker/dev

Allow root page paths (rather than specifying a magic "home" string). More UX improvements to FileManager and Pager.
This commit is contained in:
Shaun Walker 2021-10-01 11:22:02 -04:00 committed by GitHub
commit 8e6c73d2bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 99 additions and 59 deletions

View File

@ -74,7 +74,7 @@
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label> <Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'." ResourceKey="UrlPath">Url Path: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input id="path" class="form-control" @bind="@_path" /> <input id="path" class="form-control" @bind="@_path" />
</div> </div>
@ -293,11 +293,11 @@
page.SiteId = PageState.Page.SiteId; page.SiteId = PageState.Page.SiteId;
page.Name = _name; page.Name = _name;
page.Title = _title; page.Title = _title;
if (string.IsNullOrEmpty(_path)) if (string.IsNullOrEmpty(_path))
{ {
_path = _name; _path = _name;
} }
if (_path.Contains("/")) if (_path.Contains("/"))
{ {
_path = _path.Substring(_path.LastIndexOf("/") + 1); _path = _path.Substring(_path.LastIndexOf("/") + 1);

View File

@ -81,7 +81,7 @@
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label> <Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'." ResourceKey="UrlPath">Url Path: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input id="path" class="form-control" @bind="@_path" maxlength="256"/> <input id="path" class="form-control" @bind="@_path" maxlength="256"/>
</div> </div>
@ -225,9 +225,16 @@
_title = page.Title; _title = page.Title;
_path = page.Path; _path = page.Path;
if (_path.Contains("/")) if (string.IsNullOrEmpty(_path))
{ {
_path = _path.Substring(_path.LastIndexOf("/") + 1); _path = "/";
}
else
{
if (_path.Contains("/"))
{
_path = _path.Substring(_path.LastIndexOf("/") + 1);
}
} }
if (page.ParentId == null) if (page.ParentId == null)
@ -370,7 +377,8 @@
page.Name = _name; page.Name = _name;
page.Title = _title; page.Title = _title;
if (string.IsNullOrEmpty(_path) && _name.ToLower() != "home")
if (string.IsNullOrEmpty(_path))
{ {
_path = _name; _path = _name;
} }
@ -378,6 +386,7 @@
{ {
_path = _path.Substring(_path.LastIndexOf("/") + 1); _path = _path.Substring(_path.LastIndexOf("/") + 1);
} }
if (_parentid == "-1") if (_parentid == "-1")
{ {
page.ParentId = null; page.ParentId = null;

View File

@ -13,58 +13,60 @@
<div class="container-fluid px-0"> <div class="container-fluid px-0">
@if (ShowFolders || FolderId <= 0) @if (ShowFolders || FolderId <= 0)
{ {
<div class="row"><div class="col"> <div class="row">
<select class="form-select" value="@FolderId" @onchange="(e => FolderChanged(e))"> <div class="col">
@if (string.IsNullOrEmpty(Folder)) <select class="form-select" value="@FolderId" @onchange="(e => FolderChanged(e))">
{ @if (string.IsNullOrEmpty(Folder))
<option value="-1">&lt;@Localizer["Folder.Select"]&gt;</option> {
} <option value="-1">&lt;@Localizer["Folder.Select"]&gt;</option>
@foreach (Folder folder in _folders) }
{ @foreach (Folder folder in _folders)
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option> {
} <option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
</select> }
</div></div> </select>
</div>
</div>
} }
@if (ShowFiles) @if (ShowFiles)
{ {
<div class="row"><div class="col mt-1"> <div class="row mt-1">
<select class="form-select" value="@FileId" @onchange="(e => FileChanged(e))"> <div class="col">
<option value="-1">&lt;@Localizer["File.Select"]&gt;</option> <select class="form-select" value="@FileId" @onchange="(e => FileChanged(e))">
@foreach (File file in _files) <option value="-1">&lt;@Localizer["File.Select"]&gt;</option>
{ @foreach (File file in _files)
<option value="@(file.FileId)">@(file.Name)</option> {
} <option value="@(file.FileId)">@(file.Name)</option>
</select> }
</div></div> </select>
</div>
</div>
} }
@if (ShowUpload && _haseditpermission) @if (ShowUpload && _haseditpermission)
{ {
<div class="row"><div class="col mt-1"> <div class="row">
@if (UploadMultiple) <div class="col mt-2">
{ @if (UploadMultiple)
<input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple /> {
} <input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple />
else }
{ else
<input type="file" id="@_fileinputid" name="file" accept="@_filter" /> {
} <input type="file" id="@_fileinputid" name="file" accept="@_filter" />
<span class="float-end"> }
</div>
<div class="col mt-2 text-center">
<button type="button" class="btn btn-success" @onclick="UploadFile">@SharedLocalizer["Upload"]</button> <button type="button" class="btn btn-success" @onclick="UploadFile">@SharedLocalizer["Upload"]</button>
@if (ShowFiles && GetFileId() != -1) @if (ShowFiles && GetFileId() != -1)
{ {
<button type="button" class="btn btn-danger" @onclick="DeleteFile">@SharedLocalizer["Delete"]</button> <button type="button" class="btn btn-danger mx-1" @onclick="DeleteFile">@SharedLocalizer["Delete"]</button>
} }
</span>
</div></div>
<div class="row"><div class="col mt-1">
<div class="container-fluid px-0">
<div class="row">
<div class="col-6"><span id="@_progressinfoid"></span></div>
<div class="col-6"><progress id="@_progressbarid" class="mt-1" style="visibility: hidden;"></progress></div>
</div>
</div> </div>
</div></div> </div>
<div class="row">
<div class="col mt-1"><span id="@_progressinfoid" style="display: none;"></span></div>
<div class="col text-center mt-1"><progress id="@_progressbarid" class="mt-1" style="display: none;"></progress></div>
</div>
} }
</div> </div>
</div> </div>
@ -77,8 +79,8 @@
</div> </div>
@if (!string.IsNullOrEmpty(_message)) @if (!string.IsNullOrEmpty(_message))
{ {
<div class="row"> <div class="row mt-1">
<div class="col mt-1"> <div class="col">
<ModuleMessage Message="@_message" Type="@_messagetype" /> <ModuleMessage Message="@_message" Type="@_messagetype" />
</div> </div>
</div> </div>
@ -369,5 +371,7 @@
public int GetFileId() => FileId; public int GetFileId() => FileId;
public int GetFolderId() => FolderId;
public File GetFile() => _file; public File GetFile() => _file;
} }

View File

@ -215,7 +215,7 @@
} }
else else
{ {
Class = "container"; Class = "container-fluid px-0";
} }
} }

View File

@ -181,7 +181,7 @@
<value>Select whether the page is part of the site navigation or hidden</value> <value>Select whether the page is part of the site navigation or hidden</value>
</data> </data>
<data name="UrlPath.HelpText" xml:space="preserve"> <data name="UrlPath.HelpText" xml:space="preserve">
<value>Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used.</value> <value>Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'.</value>
</data> </data>
<data name="Redirect.HelpText" xml:space="preserve"> <data name="Redirect.HelpText" xml:space="preserve">
<value>Optionally enter a url which this page should redirect to when a user navigates to it</value> <value>Optionally enter a url which this page should redirect to when a user navigates to it</value>

View File

@ -169,7 +169,7 @@
<value>Select whether the page is part of the site navigation or hidden</value> <value>Select whether the page is part of the site navigation or hidden</value>
</data> </data>
<data name="UrlPath.HelpText" xml:space="preserve"> <data name="UrlPath.HelpText" xml:space="preserve">
<value>Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used.</value> <value>Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'.</value>
</data> </data>
<data name="Redirect.HelpText" xml:space="preserve"> <data name="Redirect.HelpText" xml:space="preserve">
<value>Optionally enter a url which this page should redirect to when a user navigates to it</value> <value>Optionally enter a url which this page should redirect to when a user navigates to it</value>

View File

@ -109,6 +109,9 @@ namespace Oqtane.Services
attempts += 1; attempts += 1;
} }
await interop.SetElementAttribute(id + "ProgressInfo", "style", "display: none;");
await interop.SetElementAttribute(id + "ProgressBar", "style", "display: none;");
if (!success) if (!success)
{ {
result = result.Substring(0, result.Length - 1); result = result.Substring(0, result.Length - 1);

View File

@ -247,5 +247,20 @@ namespace Oqtane.UI
return new ValueTask<bool>(Task.FromResult(false)); return new ValueTask<bool>(Task.FromResult(false));
} }
} }
public Task SetElementAttribute(string id, string attribute, string value)
{
try
{
_jsRuntime.InvokeVoidAsync(
"Oqtane.Interop.setElementAttribute",
id, attribute, value);
return Task.CompletedTask;
}
catch
{
return Task.CompletedTask;
}
}
} }
} }

View File

@ -298,10 +298,14 @@ Oqtane.Interop = {
return files; return files;
}, },
uploadFiles: function (posturl, folder, id) { uploadFiles: function (posturl, folder, id) {
var files = document.getElementById(id + 'FileInput').files; var fileinput = document.getElementById(id + 'FileInput');
var files = fileinput.files;
var progressinfo = document.getElementById(id + 'ProgressInfo'); var progressinfo = document.getElementById(id + 'ProgressInfo');
var progressbar = document.getElementById(id + 'ProgressBar'); var progressbar = document.getElementById(id + 'ProgressBar');
progressinfo.setAttribute("style", "display: inline;");
progressbar.setAttribute("style", "width: 200px; display: inline;");
for (var i = 0; i < files.length; i++) { for (var i = 0; i < files.length; i++) {
var FileChunk = []; var FileChunk = [];
var file = files[i]; var file = files[i];
@ -311,8 +315,6 @@ Oqtane.Interop = {
var EndPos = BufferChunkSize; var EndPos = BufferChunkSize;
var Size = file.size; var Size = file.size;
progressbar.setAttribute("style", "width:100%; visibility: visible;");
while (FileStreamPos < Size) { while (FileStreamPos < Size) {
FileChunk.push(file.slice(FileStreamPos, EndPos)); FileChunk.push(file.slice(FileStreamPos, EndPos));
FileStreamPos = EndPos; FileStreamPos = EndPos;
@ -332,21 +334,22 @@ Oqtane.Interop = {
var request = new XMLHttpRequest(); var request = new XMLHttpRequest();
request.open('POST', posturl, true); request.open('POST', posturl, true);
request.upload.onloadstart = function (e) { request.upload.onloadstart = function (e) {
progressbar.value = 0;
progressinfo.innerHTML = file.name + ' 0%'; progressinfo.innerHTML = file.name + ' 0%';
progressbar.value = 0;
}; };
request.upload.onprogress = function (e) { request.upload.onprogress = function (e) {
var percent = Math.ceil((e.loaded / e.total) * 100); var percent = Math.ceil((e.loaded / e.total) * 100);
progressbar.value = (percent / 100);
progressinfo.innerHTML = file.name + '[' + PartCount + '] ' + percent + '%'; progressinfo.innerHTML = file.name + '[' + PartCount + '] ' + percent + '%';
progressbar.value = (percent / 100);
}; };
request.upload.onloadend = function (e) { request.upload.onloadend = function (e) {
progressbar.value = 1;
progressinfo.innerHTML = file.name + ' 100%'; progressinfo.innerHTML = file.name + ' 100%';
progressbar.value = 1;
}; };
request.send(data); request.send(data);
} }
} }
fileinput.value = '';
}, },
refreshBrowser: function (reload, wait) { refreshBrowser: function (reload, wait) {
setInterval(function () { setInterval(function () {
@ -360,5 +363,11 @@ Oqtane.Interop = {
}, },
formValid: function (formRef) { formValid: function (formRef) {
return formRef.checkValidity(); return formRef.checkValidity();
},
setElementAttribute: function (id, attribute, value) {
var element = document.getElementById(id);
if (element !== null) {
element.setAttribute(attribute, value);
}
} }
}; };