Compare commits

...

132 Commits

Author SHA1 Message Date
19fb3120d3 Update README.md 2020-05-19 14:18:43 -04:00
4154bd0988 Merge pull request #509 from sbwalker/master
update to version 1.0.0
2020-05-19 14:07:10 -04:00
35b26c7525 update to version 1.0.0 2020-05-19 14:08:03 -04:00
52b2c876a4 performance optimizations to avoid use of reflection ( thanks to @chlupac for this suggestion ) 2020-05-19 13:39:39 -04:00
b7eeda7562 Merge pull request #508 from sbwalker/master
performance optimizations to avoid use of reflection ( thanks to @chlupac for this suggestion )
2020-05-19 13:38:30 -04:00
b59e2533ea update to .NET Core 3.2 2020-05-19 12:48:30 -04:00
a8ec5e1265 Merge pull request #507 from sbwalker/master
update to .NET Core 3.2
2020-05-19 12:47:36 -04:00
61ff097f51 default theme needs to work in local development scenarios 2020-05-19 09:17:38 -04:00
b82f69b8b0 Merge pull request #506 from sbwalker/master
default theme needs to work in local development scenarios
2020-05-19 09:16:37 -04:00
263b045c75 module creator template updates 2020-05-19 09:08:29 -04:00
a160597f6f Merge pull request #505 from sbwalker/master
module creator template updates
2020-05-19 09:07:25 -04:00
f0fe6551dd Merge pull request #24 from oqtane/master
sync
2020-05-19 08:24:12 -04:00
09b17e142e Merge pull request #503 from jimspillane/FixMergeFiles
Fix file upload merge
2020-05-19 07:52:07 -04:00
b8ce634f85 Fix file upload merge
Allow upload of file names that match the token pattern ".part_", but not in the file extension. For example, a file named, a.part_Y.txt, would not be uploaded.
2020-05-18 19:53:49 -04:00
1532eb7586 Optimized downloading of assemblies when using WebAssembly 2020-05-18 18:02:23 -04:00
9b65cd0e07 Merge pull request #502 from sbwalker/master
Optimized downloading of assemblies when using WebAssembly
2020-05-18 18:01:23 -04:00
b4596cb624 Merge pull request #11 from oqtane/master
Sync upstream
2020-05-18 15:30:43 -04:00
5e23448618 use lambas for setting resources 2020-05-18 13:34:53 -04:00
96c2a59551 Merge pull request #501 from sbwalker/master
use lambas for setting resources
2020-05-18 13:33:50 -04:00
6ae019336d changing default theme to Oqtane theme 2020-05-18 10:44:54 -04:00
0c236682b9 Merge pull request #500 from sbwalker/master
changing default theme to Oqtane theme
2020-05-18 10:44:00 -04:00
9b74262c76 Added support for module resource management 2020-05-18 09:47:37 -04:00
a13208e65d Merge pull request #499 from sbwalker/master
Added support for module resource management
2020-05-18 09:46:32 -04:00
f8ab886750 Fixed issue with loading resources 2020-05-16 22:11:58 -04:00
84b011224e Merge pull request #498 from sbwalker/master
Fixed issue with loading resources
2020-05-16 22:11:00 -04:00
c426302242 enhanced module creator to display location where module will be created 2020-05-16 13:40:59 -04:00
814e2100b2 Merge pull request #495 from sbwalker/master
enhanced module creator to display location where module will be created
2020-05-16 13:39:57 -04:00
54d4447d23 Central management of resources ( ie. stylesheets and scripts ) 2020-05-16 12:00:15 -04:00
93942d7cdd Merge pull request #492 from jimspillane/AddMissingSInCsproj
Fix module pluralization
2020-05-16 12:00:08 -04:00
0afd7d9ca4 Merge pull request #493 from sbwalker/master
Central management of resources ( ie. stylesheets and scripts )
2020-05-16 11:59:24 -04:00
3a19ced2d1 Fix module pluralization
Added 's' to the module creator sql script in the csproj to fix compilation error.
2020-05-16 10:36:16 -04:00
d5811a20e9 Merge pull request #10 from oqtane/master
Sync master
2020-05-16 10:25:28 -04:00
1b2600c6c4 Merge pull request #23 from oqtane/master
sync
2020-05-16 08:54:28 -04:00
f9cdc6d70c Merge pull request #490 from jimspillane/AddFileValidation
Add File Name validation
2020-05-16 08:53:39 -04:00
fbdf21320b Merge pull request #491 from chlupac/SettingsService
Setting service bug.
2020-05-16 08:52:13 -04:00
96f5668a3b Setting service bug. 2020-05-16 08:40:30 +02:00
13adebb36c Add File Name validation
Apply file name validation rules to the File Controller and client.
2020-05-15 23:12:24 -04:00
8a1e83ff7f Modified the package installer to use target folders ( based on the Nuget specification ) rather than file extensions 2020-05-15 17:43:45 -04:00
e698ea4d36 Merge pull request #489 from sbwalker/master
Modified the package installer to use target folders  ( based on the Nuget specification ) rather than file extensions
2020-05-15 17:42:49 -04:00
f5ce00ae7d Merge pull request #9 from oqtane/master
Sync upstream master
2020-05-15 12:56:45 -04:00
3cbb6e3e6e enable module creator to add embeddedresources to csproj for internal modules 2020-05-15 12:36:52 -04:00
9394e77fd5 Merge pull request #488 from sbwalker/master
enable module creator to add embeddedresources to csproj for internal modules
2020-05-15 12:35:52 -04:00
ac03afb146 added ability to set default container at the page level, expanded size of role description in upgrade script for 0.9.2 2020-05-15 09:50:48 -04:00
51c27ae0e5 Merge pull request #486 from sbwalker/master
added ability to set default container at the page level, expanded size of role description in upgrade script for 0.9.2
2020-05-15 09:49:45 -04:00
0ea4c4d723 Merge pull request #484 from jimspillane/MoveFolderValidationToShared
Move Path and File validation to Shared Utilities
2020-05-15 09:47:37 -04:00
b3dee737b4 Merge pull request #480 from chlupac/FileManager
FileManager Tune-Up
2020-05-15 09:46:28 -04:00
24ca9f4ded Merge pull request #485 from chlupac/FileController
File Controller bug
2020-05-15 07:28:12 -04:00
9850e249fc File Controller bug 2020-05-15 08:20:00 +02:00
5e04cb18a4 File Manager Tune-up 2020-05-15 08:18:07 +02:00
39641804f1 Move Path and File validation to Shared Utilities
Created extension methods:
IsPathValid(Folder)
IsFileValid(File)
IsPathOrFileValid(string)

Added client side validation check for Folders.
2020-05-14 22:02:57 -04:00
edc356292d Merge pull request #481 from thabaum/patch-6
container class added to pane
2020-05-14 21:34:09 -04:00
78f4af6b70 Merge pull request #482 from thabaum/patch-7
System Info input disabled changed to readonly
2020-05-14 18:41:36 -04:00
e98b8801f3 Merge pull request #483 from sbwalker/master
removed redundant assembly download logic, added security on download controller methods
2020-05-14 18:41:15 -04:00
caabac3e74 removed redundant assembly download logic, added security on download controller methods 2020-05-14 18:40:53 -04:00
422f360807 disabled changed to readonly 2020-05-14 14:58:09 -07:00
6e28fa47a2 container class added to pane
resolves issue with title border DIV not utilizing 100% pane size
2020-05-14 14:03:09 -07:00
b4f3c4ae56 Merge pull request #22 from oqtane/master
sync
2020-05-14 14:22:15 -04:00
bafe2c6666 fix module creator templates 2020-05-14 14:22:11 -04:00
5eec442442 Merge pull request #479 from sbwalker/master
fix module creator templates
2020-05-14 14:21:28 -04:00
def12489e6 Merge pull request #8 from oqtane/master
Sync master
2020-05-14 12:12:26 -04:00
82429c2545 Merge pull request #477 from jimspillane/PathTraversal
Add File and Path rules
2020-05-14 11:55:07 -04:00
aa97dd4d0d Allow modules to be installed/uninstalled with embedded scripts or IInstallable interface. Fix module uninstall issues. 2020-05-14 11:54:28 -04:00
cba5865e81 Merge pull request #478 from sbwalker/master
Allow modules to be installed/uninstalled with embedded scripts or IInstallable interface. Fix module uninstall issues.
2020-05-14 11:53:33 -04:00
8afe8e7474 Add File and Path rules
Apply the file and path naming rules found at 
https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file

Mitigate path traversal.
2020-05-14 09:53:36 -04:00
a9630e715b Merge pull request #7 from oqtane/master
Sync upstream master
2020-05-14 08:43:53 -04:00
6824b3f1b5 Merge pull request #471 from jimspillane/ReservedNameCheck
Add additional reserved names and characters
2020-05-13 16:25:27 -04:00
1cca18c4d2 Add additional reserved names and characters
Added CONIN$,CONOUT$ and characters <>:"/\|?*

Added .Split('.')[0] to folder.Name to catch names like CON.txt and allow names like CONTRACT.
2020-05-12 22:38:28 -04:00
a886ae12cc Merge pull request #6 from oqtane/master
Sync master
2020-05-12 20:52:07 -04:00
560c995564 Include AliasId in service API calls ( this is not needed for interacting with the MasterDB repository however it is needed for tenant-based logging ) 2020-05-12 20:31:31 -04:00
69a5077eda Merge pull request #470 from sbwalker/master
Include AliasId in service API calls ( this is not needed for interacting with the MasterDB repository however it is needed for tenant-based logging )
2020-05-12 20:30:27 -04:00
3efd39c74f Merge pull request #21 from oqtane/master
sync
2020-05-12 20:08:55 -04:00
bbcb054f7a Merge pull request #469 from chlupac/IClientStartup
Client assembly selection criteria changed
2020-05-12 20:07:27 -04:00
88cf30f7c6 Merge branch 'master' of https://github.com/oqtane/oqtane.framework into IClientStartup 2020-05-12 23:20:06 +02:00
4c188b782d ClientAssembly selection criteria changed 2020-05-12 23:17:37 +02:00
196e3d5865 Merge pull request #468 from sbwalker/master
updated module creator templates to use dependency injection in module components
2020-05-12 16:38:47 -04:00
6fd0efbb73 updated module creator templates to use dependency injection in module components 2020-05-12 16:31:53 -04:00
9eec0fd86b updated HtmlText module to use dependency injection 2020-05-12 15:04:07 -04:00
ad70128747 Merge pull request #466 from sbwalker/master
updated HtmlText module to use dependency injection
2020-05-12 15:04:01 -04:00
ee55b4e3cf Merge pull request #465 from sbwalker/master
add security to site template API
2020-05-12 14:38:52 -04:00
53f454e370 Merge pull request #20 from oqtane/master
sync
2020-05-12 14:37:37 -04:00
f05c7d79e3 add security to site template API 2020-05-12 14:31:18 -04:00
598b433cd2 Merge pull request #463 from chlupac/IClientStartup
IClientStartup  implementation
2020-05-12 14:31:10 -04:00
6ac4ba4617 Merge pull request #462 from mikecasas/patch-1
Update IModuleControl.cs
2020-05-12 14:30:59 -04:00
f4710f90c0 Merge pull request #464 from sbwalker/master
validate folder names, handle missing files more gracefully
2020-05-12 14:30:44 -04:00
6f3fe8d933 validate folder names, handle missing files more gracefully 2020-05-12 13:24:51 -04:00
da73d519d7 IClientStartup implementation 2020-05-12 10:00:28 +02:00
7f157582cc Update IModuleControl.cs
Added additional comments.
2020-05-11 13:47:12 -04:00
4d7ec16f36 Merge pull request #459 from chlupac/IServerStartup
IServerStartup implementation
2020-05-11 12:56:22 -04:00
7c814a67b3 IServerStartup implementation 2020-05-11 11:19:12 +02:00
c83496d814 Merge pull request #19 from oqtane/master
sync
2020-05-10 10:03:50 -04:00
83d47376cc Merge pull request #458 from jimspillane/FixContainsFiles
Fix contains files
2020-05-10 09:43:59 -04:00
a1449fb2dd Fix Uploadable files
When testing for allowable file extensions using a comma separated list, like (jpg,mp3,txt,zip), extensions such as .xt or .p3 will return true.  Adding Split(',') will test each of the extensions correctly.

Adding ToLower() will allow mixed case extensions, like .JPG or .Zip to return true.
2020-05-09 14:58:39 -04:00
2362faaee1 Merge pull request #5 from oqtane/master
Sync master
2020-05-09 14:04:36 -04:00
f6f895b516 more responsive design adjustments 2020-05-09 12:16:39 -04:00
8516e328f7 Merge pull request #457 from sbwalker/master
more responsive design adjustments
2020-05-09 12:15:41 -04:00
043f8d07de Merge pull request #18 from oqtane/master
sync
2020-05-08 17:30:44 -04:00
c2ed71ab0d added classes to all theme controls, added mobile support to Oqtane theme 2020-05-08 17:30:35 -04:00
552df0c9fc Merge pull request #455 from chlupac/NewVersion
Ignore abstract classes at loading
2020-05-08 17:30:06 -04:00
c5d12d0430 Merge pull request #456 from sbwalker/master
added classes to all theme controls, added mobile support to Oqtane theme
2020-05-08 17:29:51 -04:00
1e270e6423 Ignore abstract classes at loading 2020-05-08 21:30:31 +02:00
aaf2c96374 minor fix for placeholder content 2020-05-08 12:25:37 -04:00
86309dc264 Merge pull request #453 from sbwalker/master
minor fix for placeholder content
2020-05-08 12:24:46 -04:00
051534b80c resolved #270 - migrated raw html entry into richtexteditor control 2020-05-08 12:17:06 -04:00
d3ce5bc17c Merge pull request #452 from sbwalker/master
resolved #270 - migrated raw html entry into richtexteditor control
2020-05-08 12:16:17 -04:00
97354a9525 Update README.md 2020-05-08 08:34:31 -04:00
f07146fd50 updated external module template to support new assembly loading criteria, fixed minor issue in assembky loading logic 2020-05-07 16:24:36 -04:00
5b08cac48d Merge pull request #451 from sbwalker/master
updated external module template to support new assembly loading criteria, fixed minor issue in assembky loading logic
2020-05-07 16:23:56 -04:00
d53bdc5bb6 Merge pull request #17 from oqtane/master
sync with upstream
2020-05-07 15:28:39 -04:00
a63a659888 Merge pull request #419 from chlupac/BootswatchCdn
Bootswatch themes in Oqtane.Themes.OqtaneTheme CDN version
2020-05-07 15:25:03 -04:00
d6f3fd108b Merge pull request #449 from chlupac/LoadOptimalization
Simplified loading of oqtane assemblies
2020-05-07 15:09:32 -04:00
47f17a589f implementation of [OqtaneIgnore] class attribute in controls 2020-05-07 21:02:43 +02:00
d7ad175cd7 fixes for framework upgrade, fixes for control panel CSS styles, added AllPages attrubute for Modules, bumped version to 0.9.1 to test upgrades 2020-05-07 14:38:24 -04:00
d58b6e5d83 Merge pull request #450 from sbwalker/master
fixes for framework upgrade, fixes for control panel CSS styles, added AllPages attrubute for Modules, bumped version to 0.9.1 to test upgrades
2020-05-07 14:37:49 -04:00
e78a5e090d Bootswatch themes in Oqtane.Themes.OqtaneTheme
Theme is set in Oqtane.Client\Themes\OqtaneTheme\Default.razor
```
    protected override async Task OnParametersSetAsync()
    {
    // go to https://www.bootstrapcdn.com/bootswatch/ and take your favorite theme
    //<link href="https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css" rel="stylesheet" integrity="sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM" crossorigin="anonymous">
        await LoadBootstrapTheme("https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css","sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM");
        await IncludeCSS("Theme.css");
    }
```
2020-05-07 12:17:44 +02:00
7ca1f92f52 Merge pull request #4 from oqtane/master
Sync master
2020-05-05 21:26:18 -04:00
c394c6ea7a Resolved authentication issue #441 related to alias refactoring #439, fixed breaking change in .NET Core 3.2 related to Blazor WebAssembly identification 2020-05-05 16:28:50 -04:00
6586883979 Merge pull request #445 from sbwalker/master
Resolved authentication issue #441 related to alias refactoring #439, fixed breaking change in .NET Core 3.2 related to Blazor WebAssembly identification
2020-05-05 16:27:52 -04:00
e09fcd7e42 added CreateApiUrl method back for backward compatibility 2020-05-05 09:47:23 -04:00
b5aa6c5a48 Merge pull request #440 from sbwalker/master
added CreateApiUrl method back for backward compatibility
2020-05-05 09:46:48 -04:00
00bf917f6c Merge pull request #435 from thabaum/patch-1
Log details displayed from disabled to readonly
2020-05-05 09:15:48 -04:00
a02cfea6c9 improve performance of alias handling and allow aliases to be an unlimited number of subfolders in depth 2020-05-05 09:15:36 -04:00
db33a91c4b Merge pull request #439 from sbwalker/master
improve performance of alias handling and allow aliases to be an unlimited number of subfolders in depth
2020-05-05 09:15:01 -04:00
8f1a3c99c3 changed displayed input to readonly
Fixes issue of unable to select information displayed from input and textarea changing the select property from disabled to readonly
2020-05-04 12:14:51 -07:00
bf84f12471 fixed theme/layout handling in Add/Edit Page 2020-05-03 11:39:34 -04:00
979680f46d Merge pull request #431 from sbwalker/master
fixed theme/layout handling in Add/Edit Page
2020-05-03 11:38:52 -04:00
c30ee60433 Merge pull request #3 from oqtane/master
Sync master
2020-05-01 18:07:34 -04:00
922c7796f2 Merge pull request #429 from sbwalker/master
fixed module action import/export, improved module installation
2020-05-01 15:58:54 -04:00
45aeb17020 fixed module action import/export, improved module installation 2020-05-01 15:58:34 -04:00
e627e14233 Merge pull request #2 from oqtane/master
Sync master
2020-05-01 14:50:51 -04:00
3afa489f22 upgrade to .NET Core 3.2 RC 2020-05-01 11:32:41 -04:00
a34e2521c6 Merge pull request #428 from sbwalker/master
Upgrade to .NET Core 3.2 RC
2020-05-01 11:32:04 -04:00
4a6b12b6f9 Merge pull request #1 from oqtane/master
Sync master
2020-04-30 21:07:21 -04:00
208 changed files with 13676 additions and 12846 deletions

View File

@ -1,4 +1,5 @@
@namespace Oqtane.Modules.Admin.Files
@using System.IO
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IFileService FileService
@ -12,7 +13,7 @@
<Label For="upload" HelpText="Upload the file you want">Upload: </Label>
</td>
<td>
<FileManager UploadMultiple="true" ShowFiles="false" FolderId="@_folderId.ToString()" />
<FileManager UploadMultiple="true" ShowFiles="false" FolderId="@_folderId" />
</td>
</tr>
</table>
@ -70,18 +71,32 @@
private async Task Download()
{
if (url == string.Empty || _folderId == -1)
{
AddModuleMessage("You Must Enter A Url And Select A Folder", MessageType.Warning);
return;
}
var filename = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1);
if (!Constants.UploadableFiles.Split(',')
.Contains(Path.GetExtension(filename).ToLower().Replace(".", "")))
{
AddModuleMessage("File Could Not Be Downloaded From Url Due To Its File Extension", MessageType.Warning);
return ;
}
if (!filename.IsPathOrFileValid())
{
AddModuleMessage("You Must Enter A Url With A Valid File Name", MessageType.Warning);
return;
}
try
{
if (url != string.Empty && _folderId != -1)
{
await FileService.UploadFileAsync(url, _folderId);
await logger.LogInformation("File Downloaded Successfully From Url {Url}", url);
AddModuleMessage("File Downloaded Successfully From Url", MessageType.Success);
}
else
{
AddModuleMessage("You Must Enter A Url And Select A Folder", MessageType.Warning);
}
await FileService.UploadFileAsync(url, _folderId);
await logger.LogInformation("File Downloaded Successfully From Url {Url}", url);
AddModuleMessage("File Downloaded Successfully From Url", MessageType.Success);
}
catch (Exception ex)
{

View File

@ -25,7 +25,7 @@
</tr>
<tr>
<td>
<Label for="name" HelpText="Enter the file name">Name: </Label>
<Label for="name" HelpText="Enter the folder name">Name: </Label>
</td>
<td>
<input id="name" class="form-control" @bind="@_name" />
@ -112,51 +112,63 @@
private async Task SaveFolder()
{
if (_name == string.Empty || _parentId == -1)
{
AddModuleMessage("Folders Must Have A Parent And A Name", MessageType.Warning);
return;
}
if (!_name.IsPathOrFileValid())
{
AddModuleMessage("Folder Name Not Valid.", MessageType.Warning);
return;
}
try
{
if (_name != string.Empty && _parentId != -1)
Folder folder;
if (_folderId != -1)
{
Folder folder;
if (_folderId != -1)
{
folder = await FolderService.GetFolderAsync(_folderId);
}
else
{
folder = new Folder();
}
folder = await FolderService.GetFolderAsync(_folderId);
}
else
{
folder = new Folder();
}
folder.SiteId = PageState.Site.SiteId;
folder.SiteId = PageState.Site.SiteId;
if (_parentId == -1)
{
folder.ParentId = null;
}
else
{
folder.ParentId = _parentId;
}
if (_parentId == -1)
{
folder.ParentId = null;
}
else
{
folder.ParentId = _parentId;
}
folder.Name = _name;
folder.IsSystem = _isSystem;
folder.Permissions = _permissionGrid.GetPermissions();
folder.Name = _name;
folder.IsSystem = _isSystem;
folder.Permissions = _permissionGrid.GetPermissions();
if (_folderId != -1)
{
folder = await FolderService.UpdateFolderAsync(folder);
}
else
{
folder = await FolderService.AddFolderAsync(folder);
}
if (_folderId != -1)
{
folder = await FolderService.UpdateFolderAsync(folder);
}
else
{
folder = await FolderService.AddFolderAsync(folder);
}
if (folder != null)
{
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
await logger.LogInformation("Folder Saved {Folder}", folder);
NavigationManager.NavigateTo(NavigateUrl());
}
else
{
AddModuleMessage("Folders Must Have A Parent And A Name", MessageType.Warning);
AddModuleMessage("An Error Was Encountered Saving The Folder", MessageType.Error);
}
}
catch (Exception ex)

View File

@ -99,7 +99,7 @@
var interop = new Interop(JsRuntime);
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
var fields = new { __RequestVerificationToken = antiforgerytoken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
await interop.SubmitForm("/pages/login/", fields);
await interop.SubmitForm($"/{PageState.Alias.AliasId}/pages/login/", fields);
}
else
{

View File

@ -13,7 +13,7 @@
<Label For="dateTime" HelpText="The date and time of this log">Date/Time: </Label>
</td>
<td>
<input id="dateTime" class="form-control" @bind="@_logDate" disabled />
<input id="dateTime" class="form-control" @bind="@_logDate" readonly />
</td>
</tr>
<tr>
@ -21,7 +21,7 @@
<Label For="level" HelpText="The level of this log">Level: </Label>
</td>
<td>
<input id="level" class="form-control" @bind="@_level" disabled />
<input id="level" class="form-control" @bind="@_level" readonly />
</td>
</tr>
<tr>
@ -29,7 +29,7 @@
<Label For="feature" HelpText="The feature that was affected">Feature: </Label>
</td>
<td>
<input id="feature" class="form-control" @bind="@_feature" disabled />
<input id="feature" class="form-control" @bind="@_feature" readonly />
</td>
</tr>
<tr>
@ -37,7 +37,7 @@
<Label For="function" HelpText="The function that was performed">Function: </Label>
</td>
<td>
<input id="function" class="form-control" @bind="@_function" disabled />
<input id="function" class="form-control" @bind="@_function" readonly />
</td>
</tr>
<tr>
@ -45,7 +45,7 @@
<Label For="category" HelpText="The categories that were affected">Category: </Label>
</td>
<td>
<input id="category" class="form-control" @bind="@_category" disabled />
<input id="category" class="form-control" @bind="@_category" readonly />
</td>
</tr>
@if (_pageName != string.Empty)
@ -55,7 +55,7 @@
<Label For="page" HelpText="The page that was affected">Page: </Label>
</td>
<td>
<input id="page" class="form-control" @bind="@_pageName" disabled />
<input id="page" class="form-control" @bind="@_pageName" readonly />
</td>
</tr>
}
@ -66,7 +66,7 @@
<Label For="module" HelpText="The module that was affected">Module: </Label>
</td>
<td>
<input id="module" class="form-control" @bind="@_moduleTitle" disabled />
<input id="module" class="form-control" @bind="@_moduleTitle" readonly />
</td>
</tr>
}
@ -77,7 +77,7 @@
<Label For="user" HelpText="The user that caused this log">User: </Label>
</td>
<td>
<input id="user" class="form-control" @bind="@_username" disabled />
<input id="user" class="form-control" @bind="@_username" readonly />
</td>
</tr>
}
@ -86,7 +86,7 @@
<Label For="url" HelpText="The url the log comes from">Url: </Label>
</td>
<td>
<input id="url" class="form-control" @bind="@_url" disabled />
<input id="url" class="form-control" @bind="@_url" readonly />
</td>
</tr>
<tr>
@ -94,7 +94,7 @@
<Label For="template" HelpText="What the log is about">Template: </Label>
</td>
<td>
<input id="template" class="form-control" @bind="@_template" disabled />
<input id="template" class="form-control" @bind="@_template" readonly />
</td>
</tr>
<tr>
@ -102,7 +102,7 @@
<Label For="message" HelpText="The message that the system generated"class="control-label">Message: </Label>
</td>
<td>
<textarea id="message" class="form-control" @bind="@_message" rows="5" disabled></textarea>
<textarea id="message" class="form-control" @bind="@_message" rows="5" readonly></textarea>
</td>
</tr>
@if (!string.IsNullOrEmpty(_exception))
@ -112,7 +112,7 @@
<Label For="exception" HelpText="The exceptions generated by the system">Exception: </Label>
</td>
<td>
<textarea id="exception" class="form-control" @bind="@_exception" rows="5" disabled></textarea>
<textarea id="exception" class="form-control" @bind="@_exception" rows="5" readonly></textarea>
</td>
</tr>
}
@ -121,7 +121,7 @@
<Label For="properties" HelpText="The properties that were affected">Properties: </Label>
</td>
<td>
<textarea id="properties" class="form-control" @bind="@_properties" rows="5" disabled></textarea>
<textarea id="properties" class="form-control" @bind="@_properties" rows="5" readonly></textarea>
</td>
</tr>
<tr>
@ -129,7 +129,7 @@
<Label For="server" HelpText="The server that was affected">Server: </Label>
</td>
<td>
<input id="server" class="form-control" @bind="@_server" disabled />
<input id="server" class="form-control" @bind="@_server" readonly />
</td>
</tr>
</table>

View File

@ -3,53 +3,66 @@
@inject NavigationManager NavigationManager
@inject IModuleDefinitionService ModuleDefinitionService
@inject IModuleService ModuleService
@inject ISystemService SystemService
<table class="table table-borderless">
<table class="table table-borderless">
<tr>
<td>
<Label For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation.">Owner Name: </Label>
</td>
<td>
<input id="owner" class="form-control" @bind="@_owner" />
</td>
</tr>
<tr>
<td>
<Label For="module" HelpText="Enter a name for this module. It should be in singular form (ie. Car) and not contain spaces or punctuation.">Module Name: </Label>
</td>
<td>
<input id="module" class="form-control" @bind="@_module" />
</td>
</tr>
<tr>
<td>
<Label For="description" HelpText="Enter s short description for the module">Description: </Label>
</td>
<td>
<textarea id="description" class="form-control" @bind="@_description" rows="3"></textarea>
</td>
</tr>
<tr>
<td>
<Label For="template" HelpText="Select a module template. Internal modules are created inside of the Oqtane solution. External modules are created outside of the Oqtane solution.">Template: </Label>
</td>
<td>
<select id="template" class="form-control" @onchange="(e => TemplateChanged(e))">
<option value="-">&lt;Select Template&gt;</option>
<option value="internal">Internal</option>
<option value="external">External</option>
</select>
</td>
</tr>
@if (!string.IsNullOrEmpty(_location))
{
<tr>
<td>
<Label For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation.">Owner Name: </Label>
<Label For="location" HelpText="Location where the module will be created">Location: </Label>
</td>
<td>
<input id="owner" class="form-control" @bind="@_owner" />
<input id="module" class="form-control" @bind="@_location" readonly />
</td>
</tr>
<tr>
<td>
<Label For="module" HelpText="Enter a name for this module. It should be in singular form (ie. Car) and not contain spaces or punctuation.">Module Name: </Label>
</td>
<td>
<input id="module" class="form-control" @bind="@_module" />
</td>
</tr>
<tr>
<td>
<Label For="description" HelpText="Enter s short description for the module">Description: </Label>
</td>
<td>
<textarea id="description" class="form-control" @bind="@_description" rows="3"></textarea>
</td>
</tr>
<tr>
<td>
<Label For="template" HelpText="Select a module template. Internal modules are created inside of the Oqtane solution. External modules are created outside of the Oqtane solution.">Template: </Label>
</td>
<td>
<select id="template" class="form-control" @bind="@_template">
<option value="">&lt;Select Template&gt;</option>
<option value="internal">Internal</option>
<option value="external">External</option>
</select>
</td>
</tr>
</table>
}
</table>
<button type="button" class="btn btn-success" @onclick="CreateModule">Create Module</button>
@code {
@code {
private string _owner = string.Empty;
private string _module = string.Empty;
private string _description = string.Empty;
private string _template = string.Empty;
private string _template = "-";
private string _location = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
@ -62,9 +75,9 @@
{
try
{
if (!string.IsNullOrEmpty(_owner) && !string.IsNullOrEmpty(_module) && !string.IsNullOrEmpty(_template))
if (!string.IsNullOrEmpty(_owner) && !string.IsNullOrEmpty(_module) && _template != "-")
{
var moduleDefinition = new ModuleDefinition { Owner = _owner.Replace(" ",""), Name = _module.Replace(" ", ""), Description = _description, Template = _template };
var moduleDefinition = new ModuleDefinition { Owner = _owner.Replace(" ", ""), Name = _module.Replace(" ", ""), Description = _description, Template = _template };
await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition, ModuleState.ModuleId);
}
else
@ -77,4 +90,35 @@
await logger.LogError(ex, "Error Creating Module");
}
}
private async void TemplateChanged(ChangeEventArgs e)
{
try
{
_location = string.Empty;
_template = (string)e.Value;
if (_template != "-")
{
Dictionary<string, string> systeminfo = await SystemService.GetSystemInfoAsync();
if (systeminfo != null)
{
string[] path = systeminfo["serverpath"].Split('\\');
if (_template == "internal")
{
_location = string.Join("\\", path, 0, path.Length - 1) + "\\Oqtane.Client\\Modules\\" + _owner + "." + _module + "s";
}
else
{
_location = string.Join("\\", path, 0, path.Length - 2) + "\\" + _owner + "." + _module + "s";
}
}
}
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Getting System Info {Error}", ex.Message);
AddModuleMessage("Error Getting System Info", MessageType.Error);
}
}
}

View File

@ -2,11 +2,10 @@
@using [Owner].[Module]s.Services
@using [Owner].[Module]s.Models
@namespace [Owner].[Module]s.Modules
@namespace [Owner].[Module]s
@inherits ModuleBase
@inject I[Module]Service [Module]Service
@inject NavigationManager NavigationManager
@inject HttpClient http
@inject SiteState sitestate
<table class="table table-borderless">
<tr>
@ -29,9 +28,14 @@
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Actions => "Add,Edit";
I[Module]Service [Module]Service;
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
};
int _id;
string _name;
string _createdby;
@ -43,7 +47,6 @@
{
try
{
[Module]Service = new [Module]Service(http, sitestate, NavigationManager);
if (PageState.Action == "Edit")
{
_id = Int32.Parse(PageState.QueryString["id"]);

View File

@ -1,11 +1,10 @@
@using [Owner].[Module]s.Services
@using [Owner].[Module]s.Models
@namespace [Owner].[Module]s.Modules
@namespace [Owner].[Module]s
@inherits ModuleBase
@inject I[Module]Service [Module]Service
@inject NavigationManager NavigationManager
@inject HttpClient http
@inject SiteState sitestate
@if (_[Module]s == null)
{
@ -42,7 +41,7 @@ else
<hr />
[Module] Module Created Successfully. Use Edit Mode To Add A [Module]. You Can Access The Files At The Following Locations:<br /><br />
[RootPath]Client\<br />
- [Owner].[Module]s.Module.Client.csproj - client project<br />
- [Owner].[Module]s.Client.csproj - client project<br />
- _Imports.razor - global imports for module components<br />
- Edit.razor - component for adding or editing content<br />
- Index.razor - main component for your module **the content you are reading is in this file**<br />
@ -51,34 +50,38 @@ else
- Services\I[Module]Service.cs - interface for defining service API methods<br />
- Services\[Module]Service.cs - implements service API interface methods<br /><br />
[RootPath]Package\<br />
- [Owner].[Module]s.Module.nuspec - nuget manifest for packaging module<br />
- [Owner].[Module]s.Module.Package.csproj - packaging project<br />
- [Owner].[Module]s.nuspec - nuget manifest for packaging module<br />
- [Owner].[Module]s.Package.csproj - packaging project<br />
- debug.cmd - copies assemblies to Oqtane bin folder when in Debug mode<br />
- release.cmd - creates nuget package and deploys to Oqtane wwwroot/modules folder when in Release mode<br /><br />
[RootPath]Server\<br />
- [Owner].[Module]s.Module.Server.csproj - server project<br />
- [Owner].[Module]s.Server.csproj - server project<br />
- Controllers\[Module]Controller.cs - API methods implemented using a REST pattern<br />
- Manager\[Module]Manager.cs - implements optional module interfaces for features such as import/export of content<br />
- Repository\I[Module]Repository.cs - interface for defining repository methods<br />
- Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core<br />
- Repository\[Module]Context.cs - provides a DB Context for data access<br />
- Scripts\[Owner].[Module].1.0.0.sql - database schema definition script<br /><br />
- Scripts\[Owner].[Module].Uninstall.sql - database uninstall script<br /><br />
- Scripts\[Owner].[Module]s.1.0.0.sql - database schema definition script<br />
- Scripts\[Owner].[Module]s.Uninstall.sql - database uninstall script<br />
- wwwroot\Module.css - module style sheet<br /><br />
[RootPath]Shared\<br />
- [Owner].[Module]s.Module.Shared.csproj - shared project<br />
- [Owner].[Module]s.csproj - shared project<br />
- Models\[Module].cs - model definition<br /><br />
<!-- The content above is for informational purposes only and can be safely removed -->
@code {
I[Module]Service [Module]Service;
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
};
List<[Module]> _[Module]s;
protected override async Task OnInitializedAsync()
{
try
{
[Module]Service = new [Module]Service(http, sitestate, NavigationManager);
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
}
catch (Exception ex)

View File

@ -1,7 +1,7 @@
using Oqtane.Models;
using Oqtane.Modules;
namespace [Owner].[Module]s.Modules
namespace [Owner].[Module]s
{
public class ModuleInfo : IModule
{
@ -10,7 +10,6 @@ namespace [Owner].[Module]s.Modules
Name = "[Module]",
Description = "[Module]",
Version = "1.0.0",
Dependencies = "[Owner].[Module]s.Module.Shared",
ServerManagerType = "[ServerManagerType]",
ReleaseVersions = "1.0.0"
};

View File

@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Modules;
using Oqtane.Services;
using Oqtane.Shared;
@ -12,44 +11,39 @@ namespace [Owner].[Module]s.Services
{
public class [Module]Service : ServiceBase, I[Module]Service, IService
{
private readonly NavigationManager _navigationManager;
private readonly SiteState _siteState;
public [Module]Service(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public [Module]Service(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "[Module]"); }
}
private string Apiurl=> CreateApiUrl(_siteState.Alias, "[Module]");
public async Task<List<[Module]>> Get[Module]sAsync(int ModuleId)
{
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>(Apiurl + "?moduleid=" + ModuleId.ToString());
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>($"{Apiurl}?moduleid={ModuleId}");
return [Module]s.OrderBy(item => item.Name).ToList();
}
public async Task<[Module]> Get[Module]Async(int [Module]Id)
{
return await GetJsonAsync<[Module]>(Apiurl + "/" + [Module]Id.ToString());
return await GetJsonAsync<[Module]>($"{Apiurl}/{[Module]Id}");
}
public async Task<[Module]> Add[Module]Async([Module] [Module])
{
return await PostJsonAsync<[Module]>(Apiurl + "?entityid=" + [Module].ModuleId, [Module]);
return await PostJsonAsync<[Module]>($"{Apiurl}?entityid={[Module].ModuleId}", [Module]);
}
public async Task<[Module]> Update[Module]Async([Module] [Module])
{
return await PutJsonAsync<[Module]>(Apiurl + "/" + [Module].[Module]Id + "?entityid=" + [Module].ModuleId, [Module]);
return await PutJsonAsync<[Module]>($"{Apiurl}/{[Module].[Module]Id}?entityid={[Module].ModuleId}", [Module]);
}
public async Task Delete[Module]Async(int [Module]Id)
{
await DeleteAsync(Apiurl + "/" + [Module]Id.ToString());
await DeleteAsync($"{Apiurl}/{[Module]Id}");
}
}
}

View File

@ -1,4 +1,4 @@
@namespace [Owner].[Module]s.Modules
@namespace [Owner].[Module]s
@inherits ModuleBase
@inject ISettingService SettingService

View File

@ -7,18 +7,19 @@
<Authors>[Owner]</Authors>
<Company>[Owner]</Company>
<Description>[Description]</Description>
<Product>[Owner].[Module]s.Module</Product>
<Product>[Owner].[Module]s</Product>
<Copyright>[Owner]</Copyright>
<AssemblyName>[Owner].[Module]s.Client.Oqtane</AssemblyName>
</PropertyGroup>
<ItemGroup>
<!-- <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.0-preview5.20216.8" />-->
<!-- <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0-preview5.20216.8" PrivateAssets="all" />-->
<PackageReference Include="System.Net.Http.Json" Version="3.2.0-preview5.20210.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.0-rc1.20223.4" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0-rc1.20223.4" PrivateAssets="all" />
<PackageReference Include="System.Net.Http.Json" Version="3.2.0-rc1.20217.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\[Owner].[Module]s.Module.Shared.csproj" />
<ProjectReference Include="..\Shared\[Owner].[Module]s.Shared.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -15,4 +15,6 @@
@using Oqtane.Services
@using Oqtane.Shared
@using Oqtane.Themes
@using Oqtane.Themes.Controls
@using Oqtane.Themes.Controls
@using Oqtane.UI
@using Oqtane.Enums

View File

@ -6,9 +6,9 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Client\[Owner].[Module]s.Module.Client.csproj" />
<ProjectReference Include="..\Server\[Owner].[Module]s.Module.Server.csproj" />
<ProjectReference Include="..\Shared\[Owner].[Module]s.Module.Shared.csproj" />
<ProjectReference Include="..\Client\[Owner].[Module]s.Client.csproj" />
<ProjectReference Include="..\Server\[Owner].[Module]s.Server.csproj" />
<ProjectReference Include="..\Shared\[Owner].[Module]s.Shared.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>[Owner].[Module]s.Module</id>
<id>[Owner].[Module]s</id>
<version>1.0.0</version>
<authors>[Owner]</authors>
<owners>[Owner]</owners>
@ -20,9 +20,13 @@
</dependencies>
</metadata>
<files>
<file src="..\Client\bin\Release\netstandard2.1\[Owner].[Module]s.Module.Client.dll" target="lib" />
<file src="..\Server\bin\Release\netcoreapp3.1\[Owner].[Module]s.Module.Server.dll" target="lib" />
<file src="..\Shared\bin\Release\netstandard2.1\[Owner].[Module]s.Module.Shared.dll" target="lib" />
<file src="..\wwwroot\**\*.*" target="wwwroot" />
<file src="..\Client\bin\Release\netstandard2.1\[Owner].[Module]s.Client.Oqtane.dll" target="lib" />
<file src="..\Client\bin\Release\netstandard2.1\[Owner].[Module]s.Client.Oqtane.pdb" target="lib" />
<file src="..\Server\bin\Release\netcoreapp3.1\[Owner].[Module]s.Server.Oqtane.dll" target="lib" />
<file src="..\Server\bin\Release\netcoreapp3.1\[Owner].[Module]s.Server.Oqtane.pdb" target="lib" />
<file src="..\Shared\bin\Release\netstandard2.1\[Owner].[Module]s.Shared.Oqtane.dll" target="lib" />
<file src="..\Shared\bin\Release\netstandard2.1\[Owner].[Module]s.Shared.Oqtane.pdb" target="lib" />
<file src="..\Server\wwwroot\**\*.*" target="wwwroot" />
<file src="..\Server\content\**\*.*" target="content" />
</files>
</package>

View File

@ -1,6 +1,6 @@
XCOPY "..\Client\bin\Debug\netstandard2.1\[Owner].[Module]s.Module.Client.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Client\bin\Debug\netstandard2.1\[Owner].[Module]s.Module.Client.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Server\bin\Debug\netcoreapp3.1\[Owner].[Module]s.Module.Server.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Server\bin\Debug\netcoreapp3.1\[Owner].[Module]s.Module.Server.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Shared\bin\Debug\netstandard2.1\[Owner].[Module]s.Module.Shared.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Shared\bin\Debug\netstandard2.1\[Owner].[Module]s.Module.Shared.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Client\bin\Debug\netstandard2.1\[Owner].[Module]s.Client.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Client\bin\Debug\netstandard2.1\[Owner].[Module]s.Client.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Server\bin\Debug\netcoreapp3.1\[Owner].[Module]s.Server.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Server\bin\Debug\netcoreapp3.1\[Owner].[Module]s.Server.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Shared\bin\Debug\netstandard2.1\[Owner].[Module]s.Shared.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y
XCOPY "..\Shared\bin\Debug\netstandard2.1\[Owner].[Module]s.Shared.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y

View File

@ -1,2 +1,2 @@
"..\..\[RootFolder]\oqtane.package\nuget.exe" pack [Owner].[Module]s.Module.nuspec
"..\..\[RootFolder]\oqtane.package\nuget.exe" pack [Owner].[Module]s.nuspec
XCOPY "*.nupkg" "..\..\[RootFolder]\Oqtane.Server\wwwroot\Modules\" /Y

View File

@ -23,12 +23,12 @@ namespace [Owner].[Module]s.Manager
public bool Install(Tenant tenant, string version)
{
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]." + version + ".sql");
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]s." + version + ".sql");
}
public bool Uninstall(Tenant tenant)
{
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module].Uninstall.sql");
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]s.Uninstall.sql");
}
public string ExportModule(Module module)

View File

@ -5,20 +5,21 @@
<LangVersion>7.3</LangVersion>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<Version>1.0.0</Version>
<Product>[Owner].[Module]s.Module</Product>
<Product>[Owner].[Module]s</Product>
<Authors>[Owner]</Authors>
<Company>[Owner]</Company>
<Description>[Description]</Description>
<Copyright>[Owner]</Copyright>
<AssemblyName>[Owner].[Module]s.Server.Oqtane</AssemblyName>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Scripts\[Owner].[Module].1.0.0.sql" />
<EmbeddedResource Include="Scripts\[Owner].[Module].Uninstall.sql" />
<EmbeddedResource Include="Scripts\[Owner].[Module]s.1.0.0.sql" />
<EmbeddedResource Include="Scripts\[Owner].[Module]s.Uninstall.sql" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="3.2.0-preview5.20216.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="3.2.0-rc1.20223.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.2" />
@ -26,7 +27,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\[Owner].[Module]s.Module.Shared.csproj" />
<ProjectReference Include="..\Shared\[Owner].[Module]s.Shared.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -0,0 +1 @@
This is the location where static resources for third party libraries should be located ( the third party library assemblies will be included in the /lib folder ). They should be placed in subfolders which match the naming convention of the third party library. When the module package is deployed the static resource subfolders will be extracted under the web root.

View File

@ -0,0 +1 @@
/* Module Custom Styles */

View File

@ -0,0 +1 @@
This is the location where static resources such as images, style sheets, or scripts for this module will be located. Static assets can be organized in subfolders. When the module package is deployed the assets will be extracted under the web root in a folder that matches the module namespace.

View File

@ -4,11 +4,12 @@
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>7.3</LangVersion>
<Version>1.0.0</Version>
<Product>[Owner].[Module].Module</Product>
<Product>[Owner].[Module]s</Product>
<Authors>[Owner]</Authors>
<Company>[Owner]</Company>
<Description>[Description]</Description>
<Copyright>[Owner]</Copyright>
<AssemblyName>[Owner].[Module]s.Shared.Oqtane</AssemblyName>
</PropertyGroup>
<ItemGroup>

View File

@ -3,13 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28621.142
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module]s.Module.Client", "Client\[Owner].[Module]s.Module.Client.csproj", "{AA8E58A1-CD09-4208-BF66-A8BB341FD669}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module]s.Client", "Client\[Owner].[Module]s.Client.csproj", "{AA8E58A1-CD09-4208-BF66-A8BB341FD669}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module]s.Module.Server", "Server\[Owner].[Module]s.Module.Server.csproj", "{04B05448-788F-433D-92C0-FED35122D45A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module]s.Server", "Server\[Owner].[Module]s.Server.csproj", "{04B05448-788F-433D-92C0-FED35122D45A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module]s.Module.Shared", "Shared\[Owner].[Module]s.Module.Shared.csproj", "{18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module]s.Shared", "Shared\[Owner].[Module]s.Shared.csproj", "{18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "[Owner].[Module]s.Module.Package", "Package\[Owner].[Module]s.Module.Package.csproj", "{C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "[Owner].[Module]s.Package", "Package\[Owner].[Module]s.Package.csproj", "{C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -2,11 +2,10 @@
@using [Owner].[Module]s.Services
@using [Owner].[Module]s.Models
@namespace [Owner].[Module]s.Modules
@namespace [Owner].[Module]s
@inherits ModuleBase
@inject I[Module]Service [Module]Service
@inject NavigationManager NavigationManager
@inject HttpClient http
@inject SiteState sitestate
<table class="table table-borderless">
<tr>
@ -31,7 +30,6 @@
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Actions => "Add,Edit";
I[Module]Service [Module]Service;
int _id;
string _name;
string _createdby;
@ -43,7 +41,6 @@
{
try
{
[Module]Service = new [Module]Service(http, sitestate, NavigationManager);
if (PageState.Action == "Edit")
{
_id = Int32.Parse(PageState.QueryString["id"]);

View File

@ -1,11 +1,10 @@
@using [Owner].[Module]s.Services
@using [Owner].[Module]s.Models
@namespace [Owner].[Module]s.Modules
@namespace [Owner].[Module]s
@inherits ModuleBase
@inject I[Module]Service [Module]Service
@inject NavigationManager NavigationManager
@inject HttpClient http
@inject SiteState sitestate
@if (_[Module]s == null)
{
@ -54,22 +53,20 @@ else
- Repository\I[Module]Repository.cs - interface for defining repository methods<br />
- Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core<br />
- Repository\[Module]Context.cs - provides a DB Context for data access<br />
- Scripts\[Owner].[Module].1.0.0.sql - database schema definition script<br /><br />
- Scripts\[Owner].[Module].Uninstall.sql - database uninstall script<br /><br />
- Scripts\[Owner].[Module]s.1.0.0.sql - database schema definition script<br />
- Scripts\[Owner].[Module]s.Uninstall.sql - database uninstall script<br /><br />
[RootPath]Oqtane.Shared\Modules\[Module]\<br />
- Models\[Module].cs - model definition<br /><br />
<!-- The content above is for informational purposes only and can be safely removed -->
@code {
I[Module]Service [Module]Service;
List<[Module]> _[Module]s;
protected override async Task OnInitializedAsync()
{
try
{
[Module]Service = new [Module]Service(http, sitestate, NavigationManager);
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
}
catch (Exception ex)

View File

@ -1,7 +1,7 @@
using Oqtane.Models;
using Oqtane.Modules;
namespace [Owner].[Module]s.Modules
namespace [Owner].[Module]s
{
public class ModuleInfo : IModule
{
@ -10,7 +10,6 @@ namespace [Owner].[Module]s.Modules
Name = "[Module]",
Description = "[Module]",
Version = "1.0.0",
Dependencies = "[Owner].[Module]s.Module.Shared",
ServerManagerType = "[ServerManagerType]",
ReleaseVersions = "1.0.0"
};

View File

@ -2,7 +2,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Modules;
using Oqtane.Services;
using Oqtane.Shared;
@ -12,44 +11,39 @@ namespace [Owner].[Module]s.Services
{
public class [Module]Service : ServiceBase, I[Module]Service, IService
{
private readonly NavigationManager _navigationManager;
private readonly SiteState _siteState;
public [Module]Service(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public [Module]Service(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "[Module]"); }
}
private string Apiurl=> CreateApiUrl(_siteState.Alias, "[Module]");
public async Task<List<[Module]>> Get[Module]sAsync(int ModuleId)
{
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>(Apiurl + "?moduleid=" + ModuleId.ToString());
List<[Module]> [Module]s = await GetJsonAsync<List<[Module]>>($"{Apiurl}?moduleid={ModuleId}");
return [Module]s.OrderBy(item => item.Name).ToList();
}
public async Task<[Module]> Get[Module]Async(int [Module]Id)
{
return await GetJsonAsync<[Module]>(Apiurl + "/" + [Module]Id.ToString());
return await GetJsonAsync<[Module]>($"{Apiurl}/{[Module]Id}");
}
public async Task<[Module]> Add[Module]Async([Module] [Module])
{
return await PostJsonAsync<[Module]>(Apiurl + "?entityid=" + [Module].ModuleId, [Module]);
return await PostJsonAsync<[Module]>($"{Apiurl}?entityid={[Module].ModuleId}", [Module]);
}
public async Task<[Module]> Update[Module]Async([Module] [Module])
{
return await PutJsonAsync<[Module]>(Apiurl + "/" + [Module].[Module]Id + "?entityid=" + [Module].ModuleId, [Module]);
return await PutJsonAsync<[Module]>($"{Apiurl}/{[Module].[Module]Id}?entityid={[Module].ModuleId}", [Module]);
}
public async Task Delete[Module]Async(int [Module]Id)
{
await DeleteAsync(Apiurl + "/" + [Module]Id.ToString());
await DeleteAsync($"{Apiurl}/{[Module]Id}");
}
}
}

View File

@ -1,4 +1,4 @@
@namespace [Owner].[Module]s.Modules
@namespace [Owner].[Module]s
@inherits ModuleBase
@inject ISettingService SettingService

View File

@ -10,25 +10,13 @@ using [Owner].[Module]s.Repository;
namespace [Owner].[Module]s.Manager
{
public class [Module]Manager : IInstallable, IPortable
public class [Module]Manager : IPortable
{
private I[Module]Repository _[Module]s;
private ISqlRepository _sql;
public [Module]Manager(I[Module]Repository [Module]s, ISqlRepository sql)
public [Module]Manager(I[Module]Repository [Module]s)
{
_[Module]s = [Module]s;
_sql = sql;
}
public bool Install(Tenant tenant, string version)
{
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]." + version + ".sql");
}
public bool Uninstall(Tenant tenant)
{
return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module].Uninstall.sql");
}
public string ExportModule(Module module)

View File

@ -35,7 +35,7 @@
<Label HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation.">Module: </Label>
</td>
<td>
<FileManager Filter="nupkg" ShowFiles="false" Folder="Modules" UploadMultiple="True" />
<FileManager Filter="nupkg" ShowFiles="false" Folder="Modules" UploadMultiple="true" />
</td>
</tr>
</table>

View File

@ -24,7 +24,7 @@
</td>
<td>
<select id="container" class="form-control" @bind="@_containerType">
<option value="">&lt;Select Container&gt;</option>
<option value="-">&lt;Inherit From Page Or Site&gt;</option>
@foreach (KeyValuePair<string, string> container in _containers)
{
<option value="@container.Key">@container.Value</option>
@ -32,6 +32,17 @@
</select>
</td>
</tr>
<tr>
<td>
<Label For="allpages" HelpText="Indicate if this module should be displayed on all pages">Display On All Pages? </Label>
</td>
<td>
<select id="allpages" class="form-control" @bind="@_allPages">
<option value="True">Yes</option>
<option value="False">No</option>
</select>
</td>
</tr>
<tr>
<td>
<Label For="page" HelpText="The page that the module is on">Page: </Label>
@ -77,6 +88,7 @@
private Dictionary<string, string> _containers;
private string _title;
private string _containerType;
private string _allPages = "false";
private string _permissionNames = "";
private string _permissions;
private string _pageId;
@ -95,6 +107,15 @@
_title = ModuleState.Title;
_containers = ThemeService.GetContainerTypes(await ThemeService.GetThemesAsync());
_containerType = ModuleState.ContainerType;
if (!string.IsNullOrEmpty(PageState.Page.DefaultContainerType) && _containerType == PageState.Page.DefaultContainerType)
{
_containerType = "-";
}
if (_containerType == PageState.Site.DefaultContainerType)
{
_containerType = "-";
}
_allPages = ModuleState.AllPages.ToString();
_permissions = ModuleState.Permissions;
_permissionNames = ModuleState.ModuleDefinition.PermissionNames;
_pageId = ModuleState.PageId.ToString();
@ -102,8 +123,8 @@
_settingsModuleType = Type.GetType(ModuleState.ModuleType);
if (_settingsModuleType != null)
{
var moduleobject = Activator.CreateInstance(_settingsModuleType);
_settingstitle = (string)_settingsModuleType.GetProperty("Title").GetValue(moduleobject, null);
var moduleobject = Activator.CreateInstance(_settingsModuleType) as IModuleControl;
_settingstitle = moduleobject.Title;
if (string.IsNullOrEmpty(_settingstitle))
{
_settingstitle = "Other Settings";
@ -120,18 +141,26 @@
private async Task SaveModule()
{
var module = ModuleState;
module.Permissions = _permissionGrid.GetPermissions();
await ModuleService.UpdateModuleAsync(module);
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
pagemodule.PageId = int.Parse(_pageId);
pagemodule.Title = _title;
pagemodule.ContainerType = _containerType;
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
{
pagemodule.ContainerType = string.Empty;
}
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
{
pagemodule.ContainerType = string.Empty;
}
await PageModuleService.UpdatePageModuleAsync(pagemodule);
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
var module = ModuleState;
module.AllPages = bool.Parse(_allPages);
module.Permissions = _permissionGrid.GetPermissions();
await ModuleService.UpdateModuleAsync(module);
if (_settingsModuleType != null)
{
var moduleType = Type.GetType(ModuleState.ModuleType);

View File

@ -101,7 +101,7 @@
</td>
<td>
<select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))">
<option value="">&lt;Select Theme&gt;</option>
<option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> item in _themes)
{
if (item.Key == _themetype)
@ -122,7 +122,7 @@
</td>
<td>
<select id="Layout" class="form-control" @bind="@_layouttype">
<option value="">&lt;Select Layout&gt;</option>
<option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> panelayout in _panelayouts)
{
if (panelayout.Key == _layouttype)
@ -137,6 +137,20 @@
</select>
</td>
</tr>
<tr>
<td>
<Label For="defaultContainer" HelpText="Select the default container for the page">Default Container: </Label>
</td>
<td>
<select id="defaultContainer" class="form-control" @bind="@_containertype">
<option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> container in _containers)
{
<option value="@container.Key">@container.Value</option>
}
</select>
</td>
</tr>
<tr>
<td>
<Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label>
@ -187,6 +201,7 @@
@code {
private Dictionary<string, string> _themes;
private Dictionary<string, string> _panelayouts;
private Dictionary<string, string> _containers = new Dictionary<string, string>();
private List<Theme> _themeList;
private List<Page> _pageList;
private string _name;
@ -200,8 +215,9 @@
private string _url;
private string _ispersonalizable = "False";
private string _mode = "view";
private string _themetype = string.Empty;
private string _layouttype = string.Empty;
private string _themetype = "-";
private string _layouttype = "-";
private string _containertype = "-";
private string _icon = string.Empty;
private string _permissions = string.Empty;
private PermissionGrid _permissionGrid;
@ -216,11 +232,9 @@
_pageList = PageState.Pages;
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
_themetype = PageState.Site.DefaultThemeType;
_layouttype = PageState.Site.DefaultLayoutType;
_themes = ThemeService.GetThemeTypes(_themeList);
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
_containers = ThemeService.GetContainerTypes(_themeList);
_permissions = string.Empty;
}
@ -271,7 +285,7 @@
try
{
_themetype = (string)e.Value;
if (_themetype != string.Empty)
if (_themetype != "-")
{
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
}
@ -350,21 +364,23 @@
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
page.Url = _url;
page.EditMode = (_mode == "edit" ? true : false);
page.ThemeType = _themetype;
page.LayoutType = (_layouttype == null ? string.Empty : _layouttype);
page.Icon = (_icon == null ? string.Empty : _icon);
page.Permissions = _permissionGrid.GetPermissions();
if (page.ThemeType == PageState.Site.DefaultThemeType)
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
{
page.ThemeType = string.Empty;
}
if (page.LayoutType == PageState.Site.DefaultLayoutType)
page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty;
if (!string.IsNullOrEmpty(page.LayoutType) && page.LayoutType == PageState.Site.DefaultLayoutType)
{
page.LayoutType = string.Empty;
}
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
{
page.DefaultContainerType = string.Empty;
}
page.Icon = (_icon == null ? string.Empty : _icon);
page.Permissions = _permissionGrid.GetPermissions();
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
page.UserId = null;

View File

@ -112,7 +112,7 @@
</td>
<td>
<select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))">
<option value="">&lt;Select Theme&gt;</option>
<option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> item in _themes)
{
if (item.Key == _themetype)
@ -133,7 +133,7 @@
</td>
<td>
<select id="Layout" class="form-control" @bind="@_layouttype">
<option value="">&lt;Select Layout&gt;</option>
<option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> panelayout in _panelayouts)
{
if (panelayout.Key == _layouttype)
@ -148,6 +148,20 @@
</select>
</td>
</tr>
<tr>
<td>
<Label For="defaultContainer" HelpText="Select the default container for the page">Default Container: </Label>
</td>
<td>
<select id="defaultContainer" class="form-control" @bind="@_containertype">
<option value="-">&lt;Inherit From Site&gt;</option>
@foreach (KeyValuePair<string, string> container in _containers)
{
<option value="@container.Key">@container.Value</option>
}
</select>
</td>
</tr>
<tr>
<td>
<Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label>
@ -200,6 +214,7 @@
@code {
private Dictionary<string, string> _themes;
private Dictionary<string, string> _panelayouts;
private Dictionary<string, string> _containers = new Dictionary<string, string>();
private List<Theme> _themeList;
private List<Page> _pageList;
private int _pageId;
@ -215,8 +230,9 @@
private string _url;
private string _ispersonalizable;
private string _mode;
private string _themetype;
private string _layouttype;
private string _themetype = "-";
private string _layouttype = "-";
private string _containertype = "-";
private string _icon;
private string _permissions;
private string _createdby;
@ -241,6 +257,7 @@
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
_themes = ThemeService.GetThemeTypes(_themeList);
_containers = ThemeService.GetContainerTypes(_themeList);
_pageId = Int32.Parse(PageState.QueryString["id"]);
var page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
@ -270,8 +287,21 @@
_ispersonalizable = page.IsPersonalizable.ToString();
_mode = (page.EditMode) ? "edit" : "view";
_themetype = page.ThemeType;
if (_themetype == PageState.Site.DefaultThemeType)
{
_themetype = "-";
}
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
_layouttype = page.LayoutType;
if (_layouttype == PageState.Site.DefaultLayoutType)
{
_layouttype = "-";
}
_containertype = page.DefaultContainerType;
if (string.IsNullOrEmpty(_containertype))
{
_containertype = "-";
}
_icon = page.Icon;
_permissions = page.Permissions;
_createdby = page.CreatedBy;
@ -337,7 +367,7 @@
try
{
_themetype = (string)e.Value;
if (_themetype != string.Empty)
if (_themetype != "-")
{
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
}
@ -417,19 +447,23 @@
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
page.Url = _url;
page.EditMode = (_mode == "edit");
page.ThemeType = _themetype;
page.LayoutType = _layouttype ?? string.Empty;
page.Icon = _icon ?? string.Empty;
page.Permissions = _permissionGrid.GetPermissions();
if (page.ThemeType == PageState.Site.DefaultThemeType)
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
{
page.ThemeType = string.Empty;
}
if (page.LayoutType == PageState.Site.DefaultLayoutType)
page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty;
if (!string.IsNullOrEmpty(page.LayoutType) && page.LayoutType == PageState.Site.DefaultLayoutType)
{
page.LayoutType = string.Empty;
}
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
{
page.DefaultContainerType = string.Empty;
}
page.Icon = _icon ?? string.Empty;
page.Permissions = _permissionGrid.GetPermissions();
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
page.UserId = null;

View File

@ -39,7 +39,7 @@
<Label For="logo" HelpText="Upload a logo for the site">Logo: </Label>
</td>
<td>
<FileManager FileId="@_logofileid.ToString()" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
</td>
</tr>
<tr>
@ -47,7 +47,7 @@
<Label For="favicon" HelpText="Select Your default icon">Favicon: </Label>
</td>
<td>
<FileManager FileId="@_faviconfileid.ToString()" Filter="ico" @ref="_faviconfilemanager" />
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
</td>
</tr>
<tr>
@ -171,7 +171,7 @@
<table class="table table-borderless">
<tr>
<td>
<Label For="isEnabled" HelpText="Select whether you would like this site to be avaiable as a proggressive web application">Is Enabled? </Label>
<Label For="isEnabled" HelpText="Select whether you would like this site to be available as a Progressive Web Application (PWA)">Is Enabled? </Label>
</td>
<td>
<select id="isEnabled" class="form-control" @bind="@_pwaisenabled">
@ -182,18 +182,18 @@
</tr>
<tr>
<td>
<Label For="appIcon" HelpText="Include an application icon for your PWA">App Icon: </Label>
<Label For="appIcon" HelpText="Include an application icon for your PWA. It should be a PNG which is 192 X 192 pixels in dimension.">App Icon: </Label>
</td>
<td>
<FileManager FileId="@_pwaappiconfileid.ToString()" Filter="png" @ref="_pwaappiconfilemanager" />
<FileManager FileId="@_pwaappiconfileid" Filter="png" @ref="_pwaappiconfilemanager" />
</td>
</tr>
<tr>
<td>
<Label For="splashIcon" HelpText="Include a splash icon">Splash Icon: </Label>
<Label For="splashIcon" HelpText="Include a splash icon for your PWA. It should be a PNG which is 512 X 512 pixels in dimension.">Splash Icon: </Label>
</td>
<td>
<FileManager FileId="@_pwasplashiconfileid.ToString()" Filter="png" @ref="_pwasplashiconfilemanager" />
<FileManager FileId="@_pwasplashiconfileid" Filter="png" @ref="_pwasplashiconfilemanager" />
</td>
</tr>
</table>
@ -251,7 +251,7 @@
{
_themeList = await ThemeService.GetThemesAsync();
_aliasList = await AliasService.GetAliasesAsync();
Site site = await SiteService.GetSiteAsync(PageState.Site.SiteId, PageState.Alias);
Site site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
if (site != null)
{
_name = site.Name;
@ -364,7 +364,7 @@
if (unique)
{
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId, PageState.Alias);
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
if (site != null)
{
site.Name = _name;
@ -395,7 +395,7 @@
site.PwaSplashIconFileId = pwasplashiconfileid;
}
site = await SiteService.UpdateSiteAsync(site, PageState.Alias);
site = await SiteService.UpdateSiteAsync(site);
_urls = _urls.Replace("\n", ",");
var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

View File

@ -134,18 +134,19 @@
_aliasList = await AliasService.GetAliasesAsync();
_alias = _aliasList.Find(item => item.AliasId == Int32.Parse(PageState.QueryString["id"]));
var site = await SiteService.GetSiteAsync(_alias.SiteId, _alias);
SiteService.SetAlias(_alias);
var site = await SiteService.GetSiteAsync(_alias.SiteId);
if (site != null)
{
_name = site.Name;
_tenantList = await TenantService.GetTenantsAsync();
_tenant = _tenantList.Find(item => item.TenantId == site.TenantId).Name;
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
{
_urls += alias.Name + "\n";
}
_themetype = site.DefaultThemeType;
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
_layouttype = site.DefaultLayoutType;
@ -182,7 +183,7 @@
{
_panelayouts = new Dictionary<string, string>();
}
StateHasChanged();
}
catch (Exception ex)
@ -206,10 +207,11 @@
unique = false;
}
}
if (unique)
{
var site = await SiteService.GetSiteAsync(_alias.SiteId, _alias);
SiteService.SetAlias(_alias);
var site = await SiteService.GetSiteAsync(_alias.SiteId);
if (site != null)
{
site.Name = _name;
@ -219,11 +221,11 @@
site.DefaultContainerType = _containertype;
site.IsDeleted = (_isdeleted == null || Boolean.Parse(_isdeleted));
site = await SiteService.UpdateSiteAsync(site, _alias);
site = await SiteService.UpdateSiteAsync(site);
_urls = _urls.Replace("\n", ",");
var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
{
if (!names.Contains(alias.Name))
@ -231,7 +233,7 @@
await AliasService.DeleteAliasAsync(alias.AliasId);
}
}
foreach (string name in names)
{
if (!_aliasList.Exists(item => item.Name == name))

View File

@ -54,7 +54,8 @@ else
{
if (alias.SiteId != PageState.Site.SiteId || alias.TenantId != PageState.Site.TenantId)
{
await SiteService.DeleteSiteAsync(alias.SiteId, alias);
SiteService.SetAlias(alias);
await SiteService.DeleteSiteAsync(alias.SiteId);
await Log(alias, LogLevel.Information, "", null, "Site Deleted {SiteId}", alias.SiteId);
var aliases = await AliasService.GetAliasesAsync();

View File

@ -8,7 +8,7 @@
<Label For="version" HelpText="Framework Version">Framework Version: </Label>
</td>
<td>
<input id="version" class="form-control" @bind="@_version" disabled />
<input id="version" class="form-control" @bind="@_version" readonly />
</td>
</tr>
<tr>
@ -16,7 +16,7 @@
<Label For="runtime" HelpText="Blazor Runtime (Server or WebAssembly)">Blazor Runtime: </Label>
</td>
<td>
<input id="runtime" class="form-control" @bind="@_runtime" disabled />
<input id="runtime" class="form-control" @bind="@_runtime" readonly />
</td>
</tr>
<tr>
@ -24,7 +24,7 @@
<Label For="clrversion" HelpText="Common Language Runtime Version">CLR Version: </Label>
</td>
<td>
<input id="clrversion" class="form-control" @bind="@_clrversion" disabled />
<input id="clrversion" class="form-control" @bind="@_clrversion" readonly />
</td>
</tr>
<tr>
@ -32,7 +32,7 @@
<Label For="osversion" HelpText="Operating System Version">OS Version: </Label>
</td>
<td>
<input id="osversion" class="form-control" @bind="@_osversion" disabled />
<input id="osversion" class="form-control" @bind="@_osversion" readonly />
</td>
</tr>
<tr>
@ -40,7 +40,7 @@
<Label For="serverpath" HelpText="Server Path">Server Path: </Label>
</td>
<td>
<input id="serverpath" class="form-control" @bind="@_serverpath" disabled />
<input id="serverpath" class="form-control" @bind="@_serverpath" readonly />
</td>
</tr>
<tr>
@ -48,7 +48,7 @@
<Label For="servertime" HelpText="Server Time">Server Time: </Label>
</td>
<td>
<input id="servertime" class="form-control" @bind="@_servertime" disabled />
<input id="servertime" class="form-control" @bind="@_servertime" readonly />
</td>
</tr>
</table>

View File

@ -35,7 +35,7 @@
<Label HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation.">Theme: </Label>
</td>
<td>
<FileManager Filter="nupkg" ShowFiles="false" Folder="Themes" UploadMultiple="True" />
<FileManager Filter="nupkg" ShowFiles="false" Folder="Themes" UploadMultiple="@true" />
</td>
</tr>
</table>

View File

@ -11,29 +11,27 @@
<TabPanel Name="Download">
@if (_upgradeavailable)
{
<ModuleMessage Type="MessageType.Info" Message="Download a new version of the framework. Once you are ready click Install to complete the installation."></ModuleMessage>
@("Framework") @_package.Version <button type="button" class="btn btn-success" @onclick=@(async () => await Download(Constants.PackageId, Constants.Version))>Download</button>
<ModuleMessage Type="MessageType.Info" Message="Select The Upgrade Button To Install a New Framework Version"></ModuleMessage>
@("Framework") @_package.Version <button type="button" class="btn btn-success" @onclick=@(async () => await Download(Constants.PackageId, Constants.Version))>Upgrade</button>
}
else
{
<ModuleMessage Type="MessageType.Info" Message="Framework Is Already Up To Date"></ModuleMessage>
}
</TabPanel>
@if (_upgradeavailable)
{
<TabPanel Name="Upload">
<table class="table table-borderless">
<tr>
<td>
<Label HelpText="Upload a new framework package. Once it is uploaded click Install to complete the installation.">Framework: </Label>
<Label HelpText="Upload a framework package and select Install to complete the installation">Framework: </Label>
</td>
<td>
<FileManager Filter="nupkg" ShowFiles="false" Folder="Framework" />
</td>
</tr>
</table>
<button type="button" class="btn btn-success" @onclick="Upgrade">Install</button>
</TabPanel>
}
</TabStrip>
}

View File

@ -64,7 +64,7 @@ else
<label for="Name" class="control-label">Photo: </label>
</td>
<td>
<FileManager FileId="@photofileid.ToString()" @ref="filemanager" />
<FileManager FileId="@photofileid" @ref="filemanager" />
</td>
</tr>
</table>

View File

@ -63,7 +63,7 @@ else
<label class="control-label">Photo: </label>
</td>
<td>
<FileManager FileId="@photofileid.ToString()" @ref="filemanager" />
<FileManager FileId="@photofileid" @ref="filemanager" />
</td>
</tr>
<tr>

View File

@ -1,6 +1,6 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@attribute [OqtaneIgnore]
@if (_visible)
{
<div class="app-admin-modal">
@ -62,9 +62,9 @@
[Parameter]
public string Class { get; set; } // optional
[Parameter]
public bool Disabled { get; set; } // optional
[Parameter]
public bool Disabled { get; set; } // optional
[Parameter]
public string EditMode { get; set; } // optional - specifies if a user must be in edit mode to see the action - default is true
@ -109,8 +109,8 @@
Type moduleType = Type.GetType(typename);
if (moduleType != null)
{
var moduleobject = Activator.CreateInstance(moduleType);
security = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
var moduleobject = Activator.CreateInstance(moduleType) as IModuleControl;
security = moduleobject.SecurityAccessLevel;
}
else
{

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@inherits ModuleBase
@attribute [OqtaneIgnore]
@inject IUserService UserService
@if (_authorized)
@ -100,8 +101,8 @@
var moduleType = Type.GetType(typename);
if (moduleType != null)
{
var moduleobject = Activator.CreateInstance(moduleType);
security = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
var moduleobject = Activator.CreateInstance(moduleType) as IModuleControl;
security = moduleobject.SecurityAccessLevel;
}
else
{

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@inherits ModuleBase
@attribute [OqtaneIgnore]
@if (_text != string.Empty)
{

View File

@ -1,5 +1,7 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@attribute [OqtaneIgnore]
@inject IFolderService FolderService
@inject IFileService FileService
@inject IJSRuntime JsRuntime
@ -9,33 +11,36 @@
<div id="@Id" class="container-fluid px-0">
<div class="row">
<div class="col">
<div>
<select class="form-control" @onchange="(e => FolderChanged(e))">
@if (string.IsNullOrEmpty(Folder))
{
<option value="-1">&lt;Select Folder&gt;</option>
}
@foreach (Folder folder in _folders)
{
if (folder.FolderId == _folderid)
@if (ShowFolders || FolderId <= 0)
{
<div>
<select class="form-control" @onchange="(e => FolderChanged(e))">
@if (string.IsNullOrEmpty(Folder))
{
<option value="@(folder.FolderId)" selected>@(new string('-', folder.Level * 2))@(folder.Name)</option>
<option value="-1">&lt;Select Folder&gt;</option>
}
else
@foreach (Folder folder in _folders)
{
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
if (folder.FolderId == FolderId)
{
<option value="@(folder.FolderId)" selected>@(new string('-', folder.Level * 2))@(folder.Name)</option>
}
else
{
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
}
}
}
</select>
</div>
@if (_showfiles)
</select>
</div>
}
@if (ShowFiles)
{
<div>
<select class="form-control" @onchange="(e => FileChanged(e))">
<option value="-1">&lt;Select File&gt;</option>
@foreach (File file in _files)
{
if (file.FileId == _fileid)
if (file.FileId == FileId)
{
<option value="@(file.FileId)" selected>@(file.Name)</option>
}
@ -47,33 +52,33 @@
</select>
</div>
}
@if (_haseditpermission)
@if (ShowUpload && _haseditpermission)
{
<div>
@if (_uploadmultiple)
@if (UploadMultiple)
{
<input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple />
<input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple/>
}
else
{
<input type="file" id="@_fileinputid" name="file" accept="@_filter" />
<input type="file" id="@_fileinputid" name="file" accept="@_filter"/>
}
<span id="@_progressinfoid"></span><progress id="@_progressbarid" style="width: 150px; visibility: hidden;"></progress>
<span class="float-right">
<button type="button" class="btn btn-success" @onclick="UploadFile">Upload</button>
@if (_showfiles && GetFileId() != -1)
{
<button type="button" class="btn btn-danger" @onclick="DeleteFile">Delete</button>
}
<button type="button" class="btn btn-success" @onclick="UploadFile">Upload</button>
@if (_showfiles && GetFileId() != -1)
{
<button type="button" class="btn btn-danger" @onclick="DeleteFile">Delete</button>
}
</span>
</div>
@((MarkupString)_message)
}
@((MarkupString) _message)
</div>
@if (_image != string.Empty)
{
<div class="col-auto">
@((MarkupString)_image)
@((MarkupString) _image)
</div>
}
</div>
@ -83,15 +88,12 @@
@code {
private string _id;
private List<Folder> _folders;
private int _folderid = -1;
private List<File> _files = new List<File>();
private int _fileid = -1;
private bool _showfiles = true;
private string _fileinputid = string.Empty;
private string _progressinfoid = string.Empty;
private string _progressbarid = string.Empty;
private string _filter = "*";
private bool _uploadmultiple = false;
private bool _haseditpermission = false;
private string _message = string.Empty;
private string _image = string.Empty;
@ -104,19 +106,25 @@
public string Folder { get; set; } // optional - for setting a specific folder by default
[Parameter]
public string FolderId { get; set; } // optional - for setting a specific folderid by default
public int FolderId { get; set; } = -1; // optional - for setting a specific folderid by default
[Parameter]
public string ShowFiles { get; set; } // optional - for indicating whether a list of files should be displayed - default is true
public bool ShowFiles { get; set; } = true; // optional - for indicating whether a list of files should be displayed - default is true
[Parameter]
public string FileId { get; set; } // optional - for setting a specific file by default
public bool ShowUpload { get; set; } = true; // optional - for indicating whether a Upload controls should be displayed - default is true
[Parameter]
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
[Parameter]
public int FileId { get; set; } = -1; // optional - for setting a specific file by default
[Parameter]
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
[Parameter]
public string UploadMultiple { get; set; } // optional - enable multiple file uploads - default false
public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
protected override async Task OnInitializedAsync()
{
@ -128,56 +136,39 @@
if (!string.IsNullOrEmpty(Folder))
{
_folders = new List<Folder> {new Folder {FolderId = -1, Name = Folder}};
_folderid = -1;
FolderId = -1;
}
else
{
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
if (!string.IsNullOrEmpty(FolderId))
{
_folderid = int.Parse(FolderId);
}
}
if (!string.IsNullOrEmpty(FileId))
if (FileId != -1)
{
_fileid = int.Parse(FileId);
if (_fileid != -1)
File file = await FileService.GetFileAsync(FileId);
if (file != null)
{
File file = await FileService.GetFileAsync(int.Parse(FileId));
if (file != null)
{
_folderid = file.FolderId;
}
else
{
_fileid = -1; // file does not exist
}
FolderId = file.FolderId;
}
else
{
FileId = -1; // file does not exist
}
await SetImage();
}
if (!string.IsNullOrEmpty(ShowFiles))
{
_showfiles = bool.Parse(ShowFiles);
}
await SetImage();
if (!string.IsNullOrEmpty(Filter))
{
_filter = "." + Filter.Replace(",",",.");
_filter = "." + Filter.Replace(",", ",.");
}
await GetFiles();
// create unique id for component
// create unique id for component
_guid = Guid.NewGuid().ToString("N");
_fileinputid = _guid + "FileInput";
_progressinfoid = _guid + "ProgressInfo";
_progressbarid = _guid + "ProgressBar";
if (!string.IsNullOrEmpty(UploadMultiple))
{
_uploadmultiple = bool.Parse(UploadMultiple);
}
}
private async Task GetFiles()
@ -190,11 +181,11 @@
}
else
{
Folder folder = _folders.FirstOrDefault(item => item.FolderId == _folderid);
Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
if (folder != null)
{
_haseditpermission = UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, folder.Permissions);
_files = await FileService.GetFilesAsync(_folderid);
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.Permissions);
_files = await FileService.GetFilesAsync(FolderId);
}
else
{
@ -221,9 +212,9 @@
_message = string.Empty;
try
{
_folderid = int.Parse((string)e.Value);
FolderId = int.Parse((string) e.Value);
await GetFiles();
_fileid = -1;
FileId = -1;
_image = string.Empty;
StateHasChanged();
}
@ -237,7 +228,7 @@
private async Task FileChanged(ChangeEventArgs e)
{
_message = string.Empty;
_fileid = int.Parse((string)e.Value);
FileId = int.Parse((string) e.Value);
await SetImage();
StateHasChanged();
@ -246,21 +237,21 @@
private async Task SetImage()
{
_image = string.Empty;
if (_fileid != -1)
if (FileId != -1)
{
File file = await FileService.GetFileAsync(_fileid);
File file = await FileService.GetFileAsync(FileId);
if (file != null && file.ImageHeight != 0 && file.ImageWidth != 0)
{
var maxwidth = 200;
var maxheight = 200;
var ratioX = (double)maxwidth / (double)file.ImageWidth;
var ratioY = (double)maxheight / (double)file.ImageHeight;
var ratioX = (double) maxwidth / (double) file.ImageWidth;
var ratioY = (double) maxheight / (double) file.ImageHeight;
var ratio = ratioX < ratioY ? ratioX : ratioY;
_image = "<img src=\"" + ContentUrl(_fileid) + "\" alt=\"" + file.Name +
"\" width=\"" + Convert.ToInt32(file.ImageWidth * ratio).ToString() +
"\" height=\"" + Convert.ToInt32(file.ImageHeight * ratio).ToString() + "\" />";
_image = "<img src=\"" + ContentUrl(FileId) + "\" alt=\"" + file.Name +
"\" width=\"" + Convert.ToInt32(file.ImageWidth * ratio).ToString() +
"\" height=\"" + Convert.ToInt32(file.ImageHeight * ratio).ToString() + "\" />";
}
}
}
@ -280,7 +271,7 @@
}
else
{
result = await FileService.UploadFilesAsync(_folderid, upload, _guid);
result = await FileService.UploadFilesAsync(FolderId, upload, _guid);
}
if (result == string.Empty)
@ -294,7 +285,7 @@
var file = _files.Where(item => item.Name == upload[0]).FirstOrDefault();
if (file != null)
{
_fileid = file.FileId;
FileId = file.FileId;
await SetImage();
}
}
@ -324,21 +315,21 @@
try
{
await FileService.DeleteFileAsync(_fileid);
await logger.LogInformation("File Deleted {File}", _fileid);
await FileService.DeleteFileAsync(FileId);
await logger.LogInformation("File Deleted {File}", FileId);
_message = "<br /><div class=\"alert alert-success\" role=\"alert\">File Deleted</div>";
await GetFiles();
_fileid = -1;
FileId = -1;
await SetImage();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting File {File} {Error}", _fileid, ex.Message);
await logger.LogError(ex, "Error Deleting File {File} {Error}", FileId, ex.Message);
_message = "<br /><div class=\"alert alert-danger\" role=\"alert\">Error Deleting File</div>";
}
}
public int GetFileId() => _fileid;
public int GetFileId() => FileId;
}

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@inherits ModuleBase
@attribute [OqtaneIgnore]
@if (!string.IsNullOrEmpty(HelpText))
{
@ -41,4 +42,4 @@ else
_openLabel += ">";
}
}
}

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@inherits ModuleBase
@attribute [OqtaneIgnore]
@if (!string.IsNullOrEmpty(_message))
{

View File

@ -1,6 +1,8 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@typeparam TableItem
@attribute [OqtaneIgnore]
@typeparam TableItem
<p>
@if(Format == "Table")
@ -209,4 +211,4 @@
UpdateList(_page);
}
}
}

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@inherits ModuleBase
@attribute [OqtaneIgnore]
@inject IRoleService RoleService
@inject IUserService UserService

View File

@ -1,28 +1,82 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@attribute [OqtaneIgnore]
@inject IJSRuntime JsRuntime
@if (_filemanagervisible)
{
<FileManager @ref="_fileManager" Filter="@Constants.ImageFiles" />
@((MarkupString)_message)
<br />
}
<div class="row justify-content-center">
<button type="button" class="btn btn-success" @onclick="InsertImage">Insert Image</button>
@if (_filemanagervisible)
{
@((MarkupString)"&nbsp;&nbsp;")
<button type="button" class="btn btn-secondary" @onclick="CloseFileManager">Close</button>
}
</div>
<div class="row">
<div class ="col">
<div @ref="@_toolBar">
@ToolbarContent
</div>
<div @ref="@_editorElement">
</div>
<div class="row" style="margin-bottom: 50px;">
<div class="col">
<TabStrip>
<TabPanel Name="Rich" Heading="Rich Text Editor">
@if (_filemanagervisible)
{
<FileManager @ref="_fileManager" Filter="@Constants.ImageFiles" />
@((MarkupString)_message)
<br />
}
<div class="row justify-content-center" style="margin-bottom: 20px;">
<button type="button" class="btn btn-secondary" @onclick="RefreshRichText">Synchronize Content</button>&nbsp;&nbsp;
<button type="button" class="btn btn-primary" @onclick="InsertImage">Insert Image</button>
@if (_filemanagervisible)
{
@((MarkupString)"&nbsp;&nbsp;")
<button type="button" class="btn btn-secondary" @onclick="CloseFileManager">Close</button>
}
</div>
<div class="row">
<div class="col">
<div @ref="@_toolBar">
@if (ToolbarContent != null)
{
@ToolbarContent
}
else
{
<select class="ql-header">
<option selected=""></option>
<option value="1"></option>
<option value="2"></option>
<option value="3"></option>
<option value="4"></option>
<option value="5"></option>
</select>
<span class="ql-formats">
<button class="ql-bold"></button>
<button class="ql-italic"></button>
<button class="ql-underline"></button>
<button class="ql-strike"></button>
</span>
<span class="ql-formats">
<select class="ql-color"></select>
<select class="ql-background"></select>
</span>
<span class="ql-formats">
<button class="ql-list" value="ordered"></button>
<button class="ql-list" value="bullet"></button>
</span>
<span class="ql-formats">
<button class="ql-link"></button>
</span>
}
</div>
<div @ref="@_editorElement">
</div>
</div>
</div>
</TabPanel>
<TabPanel Name="Raw" Heading="Raw HTML Editor">
<div class="row justify-content-center" style="margin-bottom: 20px;">
<button type="button" class="btn btn-secondary" @onclick="RefreshRawHtml">Synchronize Content</button>
</div>
@if (ReadOnly)
{
<textarea class="form-control" placeholder="@Placeholder" @bind="@_content" rows="10" readonly></textarea>
}
else
{
<textarea class="form-control" placeholder="@Placeholder" @bind="@_content" rows="10"></textarea>
}
</TabPanel>
</TabStrip>
</div>
</div>
@ -31,10 +85,12 @@
private ElementReference _toolBar;
private bool _filemanagervisible = false;
private FileManager _fileManager;
private string _content = string.Empty;
private string _original = string.Empty;
private string _message = string.Empty;
[Parameter]
public RenderFragment ToolbarContent { get; set; }
public string Content { get; set; }
[Parameter]
public bool ReadOnly { get; set; } = false;
@ -42,12 +98,21 @@
[Parameter]
public string Placeholder { get; set; } = "Enter Your Content...";
// parameters only applicable to rich text editor
[Parameter]
public RenderFragment ToolbarContent { get; set; }
[Parameter]
public string Theme { get; set; } = "snow";
[Parameter]
public string DebugLevel { get; set; } = "info";
protected override void OnInitialized()
{
_content = Content; // raw HTML
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
@ -60,42 +125,57 @@
Placeholder,
Theme,
DebugLevel);
await RichTextEditorInterop.LoadEditorContent(
JsRuntime,
_editorElement, Content);
// preserve a copy of the rich text content ( Quill sanitizes content so we need to retrieve it from the editor )
_original = await RichTextEditorInterop.GetHtml(
JsRuntime,
_editorElement);
}
}
public async Task<string> GetText()
public void CloseFileManager()
{
return await RichTextEditorInterop.GetText(
_filemanagervisible = false;
_message = string.Empty;
StateHasChanged();
}
public async Task RefreshRichText()
{
await RichTextEditorInterop.LoadEditorContent(
JsRuntime,
_editorElement, _content);
}
public async Task RefreshRawHtml()
{
_content = await RichTextEditorInterop.GetHtml(
JsRuntime,
_editorElement);
StateHasChanged();
}
public async Task<string> GetHtml()
{
return await RichTextEditorInterop.GetHtml(
JsRuntime,
_editorElement);
}
// get rich text content
string content = await RichTextEditorInterop.GetHtml(
JsRuntime,
_editorElement);
public async Task<string> GetContent()
{
return await RichTextEditorInterop.GetContent(
JsRuntime,
_editorElement);
}
public async Task LoadContent(string content)
{
await RichTextEditorInterop.LoadEditorContent(
JsRuntime,
_editorElement, content);
}
public async Task EnableEditor(bool mode)
{
await RichTextEditorInterop.EnableEditor(
JsRuntime,
_editorElement, mode);
if (_original != content)
{
// rich text content has changed - return it
return content;
}
else
{
// return raw html content
return _content;
}
}
public async Task InsertImage()
@ -121,16 +201,28 @@
_filemanagervisible = true;
_message = string.Empty;
}
StateHasChanged();
}
public void CloseFileManager()
// other rich text editor methods which can be used by developers
public async Task<string> GetText()
{
_filemanagervisible = false;
_message = string.Empty;
StateHasChanged();
return await RichTextEditorInterop.GetText(
JsRuntime,
_editorElement);
}
public async Task<string> GetContent()
{
return await RichTextEditorInterop.GetContent(
JsRuntime,
_editorElement);
}
public async Task EnableEditor(bool mode)
{
await RichTextEditorInterop.EnableEditor(
JsRuntime,
_editorElement, mode);
}
}

View File

@ -2,7 +2,7 @@
using Microsoft.JSInterop;
using System.Threading.Tasks;
namespace Oqtane.UI
namespace Oqtane.Modules.Controls
{
public static class RichTextEditorInterop
{

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@inherits ModuleBase
@attribute [OqtaneIgnore]
<div class="d-flex">
<div>

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@inherits ModuleBase
@attribute [OqtaneIgnore]
@if (Name == Parent.ActiveTab)
{

View File

@ -1,5 +1,6 @@
@namespace Oqtane.Modules.Controls
@inherits ModuleBase
@inherits ModuleBase
@attribute [OqtaneIgnore]
<CascadingValue Value="this">
<div class="container-fluid">

View File

@ -3,115 +3,62 @@
@using Oqtane.Modules.Controls
@namespace Oqtane.Modules.HtmlText
@inherits ModuleBase
@inject IHtmlTextService HtmlTextService
@inject NavigationManager NavigationManager
@inject HttpClient http
@inject SiteState sitestate
<div class="row" style="margin-bottom: 50px;">
<div class="col @_visibleText">
<textarea class="form-control" @bind="@content" rows="10"></textarea>
</div>
<div class="col @_visibleRich">
<RichTextEditor @ref="@RichTextEditorHtml">
<ToolbarContent>
<select class="ql-header">
<option selected=string.Empty></option>
<option value="1"></option>
<option value="2"></option>
<option value="3"></option>
<option value="4"></option>
<option value="5"></option>
</select>
<span class="ql-formats">
<button class="ql-bold"></button>
<button class="ql-italic"></button>
<button class="ql-underline"></button>
<button class="ql-strike"></button>
</span>
<span class="ql-formats">
<select class="ql-color"></select>
<select class="ql-background"></select>
</span>
<span class="ql-formats">
<button class="ql-list" value="ordered"></button>
<button class="ql-list" value="bullet"></button>
</span>
<span class="ql-formats">
<button class="ql-link"></button>
</span>
</ToolbarContent>
</RichTextEditor>
</div>
</div>
<div class="row">
<div class="col">
@if (!RichTextEditorMode)
{
<button type="button" class="btn btn-secondary" @onclick="RichTextEditor">Rich Text Editor</button>
}
else
{
<button type="button" class="btn btn-secondary" @onclick="RawHtmlEditor">Raw HTML Editor</button>
}
<button type="button" class="btn btn-success" @onclick="SaveContent">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
</div>
</div>
<div class="row">
<div class="col">
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
</div>
</div>
@if (_content != null)
{
<RichTextEditor Content="@_content" @ref="@RichTextEditorHtml"></RichTextEditor>
<button type="button" class="btn btn-success" @onclick="SaveContent">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
@if (!string.IsNullOrEmpty(_content))
{
<br />
<br />
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
}
}
@code {
private string _visibleText = "d-none";
private string _visibleRich;
private bool _richTextEditorMode;
private RichTextEditor RichTextEditorHtml;
private string content;
private string createdby;
private DateTime createdon;
private string modifiedby;
private DateTime modifiedon;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Title => "Edit Html/Text";
public bool RichTextEditorMode
public override List<Resource> Resources => new List<Resource>()
{
get => _richTextEditorMode;
set
{
_richTextEditorMode = value;
if (_richTextEditorMode)
{
_visibleText = "d-none";
_visibleRich = string.Empty;
}
else
{
_visibleText = string.Empty;
_visibleRich = "d-none";
}
}
}
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
// the following resources should be declared in the RichTextEditor component however the framework currently only supports resource management for modules and themes
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill1.3.6.bubble.css" },
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill1.3.6.snow.css" },
new Resource { ResourceType = ResourceType.Script, Url = "js/quill1.3.6.min.js" },
new Resource { ResourceType = ResourceType.Script, Url = "js/quill-blot-formatter.min.js" },
new Resource { ResourceType = ResourceType.Script, Url = "js/quill-interop.js" }
};
protected override async Task OnAfterRenderAsync(bool firstRender)
private RichTextEditor RichTextEditorHtml;
private string _content = null;
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
protected override async Task OnInitializedAsync()
{
try
{
if (firstRender)
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{
if (content == null)
{
RichTextEditorMode = true;
await LoadText();
}
_content = htmltext.Content;
_content = _content.Replace(Constants.ContentUrl, "/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl);
_createdby = htmltext.CreatedBy;
_createdon = htmltext.CreatedOn;
_modifiedby = htmltext.ModifiedBy;
_modifiedon = htmltext.ModifiedOn;
}
else
{
_content = string.Empty;
}
}
catch (Exception ex)
@ -121,66 +68,27 @@
}
}
private async Task LoadText()
{
var htmltextservice = new HtmlTextService(http, sitestate, NavigationManager);
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{
content = htmltext.Content;
createdby = htmltext.CreatedBy;
createdon = htmltext.CreatedOn;
modifiedby = htmltext.ModifiedBy;
modifiedon = htmltext.ModifiedOn;
if (RichTextEditorMode)
{
await RichTextEditorHtml.LoadContent(content);
StateHasChanged();
}
}
}
private async Task RichTextEditor()
{
RichTextEditorMode = true;
await RichTextEditorHtml.LoadContent(content);
StateHasChanged();
}
private async Task RawHtmlEditor()
{
content = await this.RichTextEditorHtml.GetHtml();
RichTextEditorMode = false;
StateHasChanged();
}
private async Task SaveContent()
{
if (RichTextEditorMode)
{
content = await RichTextEditorHtml.GetHtml();
}
content = content.Replace(((PageState.Alias.Path == string.Empty) ? "/~" : PageState.Alias.Path) + Constants.ContentUrl, Constants.ContentUrl);
string content = await RichTextEditorHtml.GetHtml();
content = content.Replace("/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl, Constants.ContentUrl);
try
{
var htmltextservice = new HtmlTextService(http, sitestate, NavigationManager);
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{
htmltext.Content = content;
await htmltextservice.UpdateHtmlTextAsync(htmltext);
await HtmlTextService.UpdateHtmlTextAsync(htmltext);
}
else
{
htmltext = new HtmlTextInfo();
htmltext.ModuleId = ModuleState.ModuleId;
htmltext.Content = content;
await htmltextservice.AddHtmlTextAsync(htmltext);
await HtmlTextService.AddHtmlTextAsync(htmltext);
}
await logger.LogInformation("Html/Text Content Saved {HtmlText}", htmltext);
NavigationManager.NavigateTo(NavigateUrl());
}
@ -190,5 +98,4 @@
AddModuleMessage("Error Saving Content", MessageType.Error);
}
}
}

View File

@ -1,36 +1,32 @@
@using Oqtane.Modules.HtmlText.Services
@using Oqtane.Modules.HtmlText.Models
@namespace Oqtane.Modules.HtmlText
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject HttpClient http
@inject SiteState sitestate
@inject IHtmlTextService HtmlTextService
@((MarkupString)content)
@if (PageState.EditMode)
{
<br />
}
<ActionLink Action="Edit" />
@if (PageState.EditMode)
{
<br /><br />
<br /><ActionLink Action="Edit" /><br /><br />
}
@code {
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
};
private string content = "";
protected override async Task OnParametersSetAsync()
{
try
{
var htmltextservice = new HtmlTextService(http, sitestate, NavigationManager);
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{
content = htmltext.Content;
content = content.Replace(Constants.ContentUrl, ((PageState.Alias.Path == "") ? "/~" : PageState.Alias.Path) + Constants.ContentUrl);
content = content.Replace(Constants.ContentUrl, "/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl);
}
}
catch (Exception ex)

View File

@ -2,60 +2,42 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Modules.HtmlText.Models;
using Oqtane.Services;
using Oqtane.Shared;
namespace Oqtane.Modules.HtmlText.Services
{
public class HtmlTextService : ServiceBase, IHtmlTextService
{
private readonly NavigationManager _navigationManager;
public class HtmlTextService : ServiceBase, IHtmlTextService, IService
{
private readonly SiteState _siteState;
public HtmlTextService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public HtmlTextService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string ApiUrl => CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "HtmlText");
private string ApiUrl => CreateApiUrl(_siteState.Alias, "HtmlText");
public async Task<HtmlTextInfo> GetHtmlTextAsync(int moduleId)
{
HtmlTextInfo htmlText;
try
{
//because GetJsonAsync() returns an error if no content exists for the ModuleId ( https://github.com/aspnet/AspNetCore/issues/14041 )
//null value is transfered as empty list
var htmlTextList = await GetJsonAsync<List<HtmlTextInfo>>(ApiUrl + "/" + moduleId + "?entityid=" + moduleId);
htmlText = htmlTextList.FirstOrDefault();
}
catch
{
htmlText = null;
}
return htmlText;
var htmltext = await GetJsonAsync<List<HtmlTextInfo>>($"{ApiUrl}/{moduleId}?entityid={moduleId}");
return htmltext.FirstOrDefault();
}
public async Task AddHtmlTextAsync(HtmlTextInfo htmlText)
{
await PostJsonAsync(ApiUrl + "?entityid=" + htmlText.ModuleId, htmlText);
await PostJsonAsync($"{ApiUrl}?entityid={htmlText.ModuleId}", htmlText);
}
public async Task UpdateHtmlTextAsync(HtmlTextInfo htmlText)
{
await PutJsonAsync(ApiUrl + "/" + htmlText.HtmlTextId + "?entityid=" + htmlText.ModuleId, htmlText);
await PutJsonAsync($"{ApiUrl}/{htmlText.HtmlTextId}?entityid={htmlText.ModuleId}", htmlText);
}
public async Task DeleteHtmlTextAsync(int moduleId)
{
await DeleteAsync(ApiUrl + "/" + moduleId + "?entityid=" + moduleId);
await DeleteAsync($"{ApiUrl}/{moduleId}?entityid={moduleId}");
}
}
}

View File

@ -6,10 +6,11 @@ using Oqtane.Services;
using System;
using Oqtane.Enums;
using Oqtane.UI;
using System.Collections.Generic;
namespace Oqtane.Modules
{
public class ModuleBase : ComponentBase, IModuleControl
public abstract class ModuleBase : ComponentBase, IModuleControl
{
private Logger _logger;
@ -37,6 +38,9 @@ namespace Oqtane.Modules
public virtual bool UseAdminContainer { get { return true; } }
public virtual List<Resource> Resources { get; set; }
// path method
public string ModulePath()
@ -87,7 +91,7 @@ namespace Oqtane.Modules
public string ContentUrl(int fileid)
{
return Utilities.ContentUrl(PageState.Alias.Path, fileid);
return Utilities.ContentUrl(PageState.Alias, fileid);
}
// user feedback methods

View File

@ -6,7 +6,7 @@
<LangVersion>7.3</LangVersion>
<RazorLangVersion>3.0</RazorLangVersion>
<Configurations>Debug;Release</Configurations>
<Version>0.9.0</Version>
<Version>1.0.0</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
@ -27,10 +27,11 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.0-preview5.20216.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0-preview5.20216.8" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.1.2" />
<PackageReference Include="System.Net.Http.Json" Version="3.2.0-preview5.20210.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="3.2.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.1.4" />
<PackageReference Include="System.Net.Http.Json" Version="3.2.0" />
</ItemGroup>
<ItemGroup>

View File

@ -4,12 +4,16 @@ using System.Threading.Tasks;
using Oqtane.Services;
using System.Reflection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using Oqtane.Modules;
using Oqtane.Shared;
using Oqtane.Providers;
using Microsoft.AspNetCore.Components.Authorization;
using System.IO.Compression;
using System.IO;
namespace Oqtane.Client
{
@ -19,10 +23,9 @@ namespace Oqtane.Client
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
HttpClient httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)};
builder.Services.AddSingleton(
new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }
);
builder.Services.AddSingleton(httpClient);
builder.Services.AddOptions();
// register auth services
@ -57,14 +60,16 @@ namespace Oqtane.Client
builder.Services.AddScoped<ISqlService, SqlService>();
builder.Services.AddScoped<ISystemService, SystemService>();
await LoadClientAssemblies(httpClient);
// dynamically register module contexts and repository services
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] implementationtypes = assembly.GetTypes()
.Where(item => item.GetInterfaces().Contains(typeof(IService)))
.ToArray();
foreach (Type implementationtype in implementationtypes)
var implementationTypes = assembly.GetTypes()
.Where(item => item.GetInterfaces().Contains(typeof(IService)));
foreach (Type implementationtype in implementationTypes)
{
Type servicetype = Type.GetType(implementationtype.AssemblyQualifiedName.Replace(implementationtype.Name, "I" + implementationtype.Name));
if (servicetype != null)
@ -76,9 +81,62 @@ namespace Oqtane.Client
builder.Services.AddScoped(implementationtype, implementationtype); // no interface defined for service
}
}
assembly.GetInstances<IClientStartup>()
.ToList()
.ForEach(x => x.ConfigureServices(builder.Services));
}
await builder.Build().RunAsync();
}
private static async Task LoadClientAssemblies(HttpClient http)
{
// get list of loaded assemblies on the client
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).ToList();
// get assemblies from server and load into client app domain
var zip = await http.GetByteArrayAsync($"/~/api/Installation/load");
// asemblies and debug symbols are packaged in a zip file
using (ZipArchive archive = new ZipArchive(new MemoryStream(zip)))
{
Dictionary<string, byte[]> dlls = new Dictionary<string, byte[]>();
Dictionary<string, byte[]> pdbs = new Dictionary<string, byte[]>();
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (!assemblies.Contains(Path.GetFileNameWithoutExtension(entry.Name)))
{
using (var memoryStream = new MemoryStream())
{
entry.Open().CopyTo(memoryStream);
byte[] file = memoryStream.ToArray();
switch (Path.GetExtension(entry.Name))
{
case ".dll":
dlls.Add(entry.Name, file);
break;
case ".pdb":
pdbs.Add(entry.Name, file);
break;
}
}
}
}
foreach (var item in dlls)
{
if (pdbs.ContainsKey(item.Key))
{
Assembly.Load(item.Value, pdbs[item.Key]);
}
else
{
Assembly.Load(item.Value);
}
}
}
}
}
}

View File

@ -2,6 +2,7 @@
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
@ -29,7 +30,7 @@ namespace Oqtane.Providers
{
// get HttpClient lazily from IServiceProvider as you cannot use standard dependency injection due to the AuthenticationStateProvider being initialized prior to NavigationManager ( https://github.com/aspnet/AspNetCore/issues/11867 )
var http = _serviceProvider.GetRequiredService<HttpClient>();
string apiurl = ServiceBase.CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "User") + "/authenticate";
string apiurl = "/~/api/User/authenticate";
User user = await http.GetFromJsonAsync<User>(apiurl);
ClaimsIdentity identity = new ClaimsIdentity();

View File

@ -2,32 +2,24 @@
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
//using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
using System.Net;
using System;
using System.Net.Http.Json;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class AliasService : ServiceBase, IAliasService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public AliasService(HttpClient http, SiteState siteState, NavigationManager navigationManager) :base(http)
private readonly SiteState _siteState;
public AliasService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Alias"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Alias");
public async Task<List<Alias>> GetAliasesAsync()
{
@ -37,22 +29,13 @@ namespace Oqtane.Services
public async Task<Alias> GetAliasAsync(int aliasId)
{
return await GetJsonAsync<Alias>($"{Apiurl}/{aliasId.ToString()}");
return await GetJsonAsync<Alias>($"{Apiurl}/{aliasId}");
}
public async Task<Alias> GetAliasAsync(string url, DateTime lastSyncDate)
public async Task<Alias> GetAliasAsync(string name, DateTime lastSyncDate)
{
Uri uri = new Uri(url);
string name = uri.Authority;
if (uri.Segments.Count() > 1)
{
name += "/" + uri.Segments[1];
}
if (name.EndsWith("/"))
{
name = name.Substring(0, name.Length - 1);
}
return await GetJsonAsync<Alias>($"{Apiurl}/name/{WebUtility.UrlEncode(name)}?lastsyncdate={lastSyncDate.ToString("yyyyMMddHHmmssfff")}");
name = (string.IsNullOrEmpty(name)) ? "~" : name;
return await GetJsonAsync<Alias>($"{Apiurl}/name/{WebUtility.UrlEncode(name)}?sync={lastSyncDate.ToString("yyyyMMddHHmmssfff")}");
}
public async Task<Alias> AddAliasAsync(Alias alias)
@ -62,11 +45,11 @@ namespace Oqtane.Services
public async Task<Alias> UpdateAliasAsync(Alias alias)
{
return await PutJsonAsync<Alias>($"{Apiurl}/{alias.AliasId.ToString()}", alias);
return await PutJsonAsync<Alias>($"{Apiurl}/{alias.AliasId}", alias);
}
public async Task DeleteAliasAsync(int aliasId)
{
await DeleteAsync($"{Apiurl}/{aliasId.ToString()}");
await DeleteAsync($"{Apiurl}/{aliasId}");
}
}
}

View File

@ -3,7 +3,6 @@ using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using Oqtane.Models;
using Oqtane.Shared;
@ -14,21 +13,15 @@ namespace Oqtane.Services
public class FileService : ServiceBase, IFileService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
private readonly IJSRuntime _jsRuntime;
public FileService(HttpClient http, SiteState siteState, NavigationManager navigationManager,
IJSRuntime jsRuntime) : base(http)
public FileService(HttpClient http, SiteState siteState, IJSRuntime jsRuntime) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
_jsRuntime = jsRuntime;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "File"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "File");
public async Task<List<File>> GetFilesAsync(int folderId)
{
@ -54,7 +47,7 @@ namespace Oqtane.Services
public async Task<File> GetFileAsync(int fileId)
{
return await GetJsonAsync<File>($"{Apiurl}/{fileId.ToString()}");
return await GetJsonAsync<File>($"{Apiurl}/{fileId}");
}
public async Task<File> AddFileAsync(File file)
@ -64,17 +57,17 @@ namespace Oqtane.Services
public async Task<File> UpdateFileAsync(File file)
{
return await PutJsonAsync<File>($"{Apiurl}/{file.FileId.ToString()}", file);
return await PutJsonAsync<File>($"{Apiurl}/{file.FileId}", file);
}
public async Task DeleteFileAsync(int fileId)
{
await DeleteAsync($"{Apiurl}/{fileId.ToString()}");
await DeleteAsync($"{Apiurl}/{fileId}");
}
public async Task<File> UploadFileAsync(string url, int folderId)
{
return await GetJsonAsync<File>($"{Apiurl}/upload?url={WebUtility.UrlEncode(url)}&folderid={folderId.ToString()}");
return await GetJsonAsync<File>($"{Apiurl}/upload?url={WebUtility.UrlEncode(url)}&folderid={folderId}");
}
public async Task<string> UploadFilesAsync(int folderId, string[] files, string id)
@ -124,7 +117,7 @@ namespace Oqtane.Services
public async Task<byte[]> DownloadFileAsync(int fileId)
{
return await GetByteArrayAsync($"{Apiurl}/download/{fileId.ToString()}");
return await GetByteArrayAsync($"{Apiurl}/download/{fileId}");
}
}
}

View File

@ -2,7 +2,6 @@
using System.Threading.Tasks;
using System.Linq;
using System.Net.Http;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
using System;
@ -14,26 +13,24 @@ namespace Oqtane.Services
public class FolderService : ServiceBase, IFolderService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public FolderService(HttpClient http, SiteState siteState, NavigationManager navigationManager):base(http)
public FolderService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string ApiUrl => CreateApiUrl(_siteState.Alias, _navigationManager.Uri, EntityNames.Folder);
private string ApiUrl => CreateApiUrl(_siteState.Alias, "Folder");
public async Task<List<Folder>> GetFoldersAsync(int siteId)
{
List<Folder> folders = await GetJsonAsync<List<Folder>>($"{ApiUrl}?siteid={siteId.ToString()}");
List<Folder> folders = await GetJsonAsync<List<Folder>>($"{ApiUrl}?siteid={siteId}");
folders = GetFoldersHierarchy(folders);
return folders;
}
public async Task<Folder> GetFolderAsync(int folderId)
{
return await GetJsonAsync<Folder>($"{ApiUrl}/{folderId.ToString()}");
return await GetJsonAsync<Folder>($"{ApiUrl}/{folderId}");
}
public async Task<Folder> GetFolderAsync(int siteId, [NotNull] string folderPath)
@ -55,7 +52,7 @@ namespace Oqtane.Services
public async Task<Folder> UpdateFolderAsync(Folder folder)
{
return await PutJsonAsync<Folder>($"{ApiUrl}/{folder.FolderId.ToString()}", folder);
return await PutJsonAsync<Folder>($"{ApiUrl}/{folder.FolderId}", folder);
}
public async Task UpdateFolderOrderAsync(int siteId, int folderId, int? parentId)
@ -63,12 +60,12 @@ namespace Oqtane.Services
var parent = parentId == null
? string.Empty
: parentId.ToString();
await PutAsync($"{ApiUrl}/?siteid={siteId.ToString()}&folderid={folderId.ToString()}&parentid={parent}");
await PutAsync($"{ApiUrl}/?siteid={siteId}&folderid={folderId}&parentid={parent}");
}
public async Task DeleteFolderAsync(int folderId)
{
await DeleteAsync($"{ApiUrl}/{folderId.ToString()}");
await DeleteAsync($"{ApiUrl}/{folderId}");
}
private static List<Folder> GetFoldersHierarchy(List<Folder> folders)

View File

@ -1,23 +1,15 @@
using Oqtane.Models;
using System.Threading.Tasks;
using System.Net.Http;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class InstallationService : ServiceBase, IInstallationService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public InstallationService(HttpClient http):base(http) { }
public InstallationService(HttpClient http, SiteState siteState, NavigationManager navigationManager):base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string ApiUrl => CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Installation");
private string ApiUrl => CreateApiUrl("Installation");
public async Task<Installation> IsInstalled()
{

View File

@ -12,7 +12,6 @@ namespace Oqtane.Services
Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
Task InstallModuleDefinitionsAsync();
Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId);
Task LoadModuleDefinitionsAsync(int siteId, Runtime runtime);
Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId);
}
}

View File

@ -6,14 +6,16 @@ namespace Oqtane.Services
{
public interface ISiteService
{
Task<List<Site>> GetSitesAsync(Alias alias);
void SetAlias(Alias alias);
Task<Site> GetSiteAsync(int siteId, Alias alias);
Task<List<Site>> GetSitesAsync();
Task<Site> AddSiteAsync(Site site, Alias alias);
Task<Site> GetSiteAsync(int siteId);
Task<Site> UpdateSiteAsync(Site site, Alias alias);
Task<Site> AddSiteAsync(Site site);
Task DeleteSiteAsync(int siteId, Alias alias);
Task<Site> UpdateSiteAsync(Site site);
Task DeleteSiteAsync(int siteId);
}
}

View File

@ -11,8 +11,6 @@ namespace Oqtane.Services
Task<User> AddUserAsync(User user);
Task<User> AddUserAsync(User user, Alias alias);
Task<User> UpdateUserAsync(User user);
Task DeleteUserAsync(int userId);

View File

@ -2,7 +2,6 @@
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
@ -11,19 +10,13 @@ namespace Oqtane.Services
public class JobLogService : ServiceBase, IJobLogService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public JobLogService(HttpClient http, SiteState siteState, NavigationManager navigationManager) :base(http)
public JobLogService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "JobLog"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "JobLog");
public async Task<List<JobLog>> GetJobLogsAsync()
{
@ -33,7 +26,7 @@ namespace Oqtane.Services
public async Task<JobLog> GetJobLogAsync(int jobLogId)
{
return await GetJsonAsync<JobLog>($"{Apiurl}/{jobLogId.ToString()}");
return await GetJsonAsync<JobLog>($"{Apiurl}/{jobLogId}");
}
public async Task<JobLog> AddJobLogAsync(JobLog joblog)
@ -43,11 +36,11 @@ namespace Oqtane.Services
public async Task<JobLog> UpdateJobLogAsync(JobLog joblog)
{
return await PutJsonAsync<JobLog>($"{Apiurl}/{joblog.JobLogId.ToString()}", joblog);
return await PutJsonAsync<JobLog>($"{Apiurl}/{joblog.JobLogId}", joblog);
}
public async Task DeleteJobLogAsync(int jobLogId)
{
await DeleteAsync($"{Apiurl}/{jobLogId.ToString()}");
await DeleteAsync($"{Apiurl}/{jobLogId}");
}
}
}

View File

@ -2,7 +2,6 @@
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
@ -10,22 +9,15 @@ namespace Oqtane.Services
{
public class JobService : ServiceBase, IJobService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public JobService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public JobService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Job"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Job");
public async Task<List<Job>> GetJobsAsync()
{
List<Job> jobs = await GetJsonAsync<List<Job>>(Apiurl);
@ -34,7 +26,7 @@ namespace Oqtane.Services
public async Task<Job> GetJobAsync(int jobId)
{
return await GetJsonAsync<Job>($"{Apiurl}/{jobId.ToString()}");
return await GetJsonAsync<Job>($"{Apiurl}/{jobId}");
}
public async Task<Job> AddJobAsync(Job job)
@ -44,21 +36,21 @@ namespace Oqtane.Services
public async Task<Job> UpdateJobAsync(Job job)
{
return await PutJsonAsync<Job>($"{Apiurl}/{job.JobId.ToString()}", job);
return await PutJsonAsync<Job>($"{Apiurl}/{job.JobId}", job);
}
public async Task DeleteJobAsync(int jobId)
{
await DeleteAsync($"{Apiurl}/{jobId.ToString()}");
await DeleteAsync($"{Apiurl}/{jobId}");
}
public async Task StartJobAsync(int jobId)
{
await GetAsync($"{Apiurl}/start/{jobId.ToString()}");
await GetAsync($"{Apiurl}/start/{jobId}");
}
public async Task StopJobAsync(int jobId)
{
await GetAsync($"{Apiurl}/stop/{jobId.ToString()}");
await GetAsync($"{Apiurl}/stop/{jobId}");
}
}
}

View File

@ -23,19 +23,16 @@ namespace Oqtane.Services
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Log"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Log");
public async Task<List<Log>> GetLogsAsync(int siteId, string level, string function, int rows)
{
return await GetJsonAsync<List<Log>>($"{Apiurl}?siteid={siteId.ToString()}&level={level}&function={function}&rows={rows.ToString()}");
return await GetJsonAsync<List<Log>>($"{Apiurl}?siteid={siteId}&level={level}&function={function}&rows={rows}");
}
public async Task<Log> GetLogAsync(int logId)
{
return await GetJsonAsync<Log>($"{Apiurl}/{logId.ToString()}");
return await GetJsonAsync<Log>($"{Apiurl}/{logId}");
}
public async Task Log(int? pageId, int? moduleId, int? userId, string category, string feature, LogFunction function, LogLevel level, Exception exception, string message, params object[] args)
@ -52,6 +49,7 @@ namespace Oqtane.Services
}
else
{
base.Alias = alias;
log.SiteId = alias.SiteId;
}
log.PageId = pageId;
@ -69,7 +67,7 @@ namespace Oqtane.Services
log.Message = message;
log.MessageTemplate = "";
log.Properties = JsonSerializer.Serialize(args);
await PostJsonAsync(CreateCrossTenantUrl(Apiurl, alias), log);
await PostJsonAsync(Apiurl, log);
}
}
}

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using System;
using System.Reflection;
using Oqtane.Shared;
@ -15,34 +14,29 @@ namespace Oqtane.Services
{
private readonly HttpClient _http;
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public ModuleDefinitionService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public ModuleDefinitionService(HttpClient http, SiteState siteState) : base(http)
{
_http = http;
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, EntityNames.ModuleDefinition); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "ModuleDefinition");
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync(int siteId)
{
List<ModuleDefinition> moduledefinitions = await GetJsonAsync<List<ModuleDefinition>>($"{Apiurl}?siteid={siteId.ToString()}");
List<ModuleDefinition> moduledefinitions = await GetJsonAsync<List<ModuleDefinition>>($"{Apiurl}?siteid={siteId}");
return moduledefinitions.OrderBy(item => item.Name).ToList();
}
public async Task<ModuleDefinition> GetModuleDefinitionAsync(int moduleDefinitionId, int siteId)
{
return await GetJsonAsync<ModuleDefinition>($"{Apiurl}/{moduleDefinitionId.ToString()}?siteid={siteId.ToString()}");
return await GetJsonAsync<ModuleDefinition>($"{Apiurl}/{moduleDefinitionId}?siteid={siteId}");
}
public async Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition)
{
await PutJsonAsync($"{Apiurl}/{moduleDefinition.ModuleDefinitionId.ToString()}", moduleDefinition);
await PutJsonAsync($"{Apiurl}/{moduleDefinition.ModuleDefinitionId}", moduleDefinition);
}
public async Task InstallModuleDefinitionsAsync()
@ -52,49 +46,12 @@ namespace Oqtane.Services
public async Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId)
{
await DeleteAsync($"{Apiurl}/{moduleDefinitionId.ToString()}?siteid={siteId.ToString()}");
await DeleteAsync($"{Apiurl}/{moduleDefinitionId}?siteid={siteId}");
}
public async Task LoadModuleDefinitionsAsync(int siteId, Runtime runtime)
{
// get list of modules from the server
List<ModuleDefinition> moduledefinitions = await GetModuleDefinitionsAsync(siteId);
// download assemblies to browser when running client-side Blazor
if (runtime == Runtime.WebAssembly)
{
// get list of loaded assemblies on the client ( in the client-side hosting module the browser client has its own app domain )
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (ModuleDefinition moduledefinition in moduledefinitions)
{
// if a module has dependencies, check if they are loaded
if (moduledefinition.Dependencies != "")
{
foreach (string dependency in moduledefinition.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
string assemblyname = dependency.Replace(".dll", "");
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{assemblyname}.dll");
Assembly.Load(bytes);
}
}
}
// check if the module assembly is loaded
if (assemblies.Where(item => item.FullName.StartsWith(moduledefinition.AssemblyName + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{moduledefinition.AssemblyName}.dll");
Assembly.Load(bytes);
}
}
}
}
public async Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId)
{
await PostJsonAsync($"{Apiurl}?moduleid={moduleId.ToString()}", moduleDefinition);
await PostJsonAsync($"{Apiurl}?moduleid={moduleId}", moduleDefinition);
}
}
}

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
namespace Oqtane.Services
@ -12,23 +11,17 @@ namespace Oqtane.Services
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public ModuleService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public ModuleService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Module"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Module");
public async Task<List<Module>> GetModulesAsync(int siteId)
{
List<Module> modules = await GetJsonAsync<List<Module>>($"{Apiurl}?siteid={siteId.ToString()}");
List<Module> modules = await GetJsonAsync<List<Module>>($"{Apiurl}?siteid={siteId}");
modules = modules
.OrderBy(item => item.Order)
.ToList();
@ -37,7 +30,7 @@ namespace Oqtane.Services
public async Task<Module> GetModuleAsync(int moduleId)
{
return await GetJsonAsync<Module>($"{Apiurl}/{moduleId.ToString()}");
return await GetJsonAsync<Module>($"{Apiurl}/{moduleId}");
}
public async Task<Module> AddModuleAsync(Module module)
@ -47,7 +40,7 @@ namespace Oqtane.Services
public async Task<Module> UpdateModuleAsync(Module module)
{
return await PutJsonAsync<Module>($"{Apiurl}/{module.ModuleId.ToString()}", module);
return await PutJsonAsync<Module>($"{Apiurl}/{module.ModuleId}", module);
}
public async Task DeleteModuleAsync(int moduleId)
@ -62,7 +55,7 @@ namespace Oqtane.Services
public async Task<string> ExportModuleAsync(int moduleId)
{
return await GetStringAsync($"{Apiurl}/export?moduleid={moduleId.ToString()}");
return await GetStringAsync($"{Apiurl}/export?moduleid={moduleId}");
}
}
}

View File

@ -1,7 +1,6 @@
using Oqtane.Models;
using System.Threading.Tasks;
using System.Net.Http;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
using System.Collections.Generic;
using System.Linq;
@ -11,29 +10,24 @@ namespace Oqtane.Services
public class NotificationService : ServiceBase, INotificationService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public NotificationService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public NotificationService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Notification"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Notification");
public async Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId)
{
var notifications = await GetJsonAsync<List<Notification>>($"{Apiurl}?siteid={siteId.ToString()}&direction={direction.ToLower()}&userid={userId.ToString()}");
var notifications = await GetJsonAsync<List<Notification>>($"{Apiurl}?siteid={siteId}&direction={direction.ToLower()}&userid={userId}");
return notifications.OrderByDescending(item => item.CreatedOn).ToList();
}
public async Task<Notification> GetNotificationAsync(int notificationId)
{
return await GetJsonAsync<Notification>($"{Apiurl}/{notificationId.ToString()}");
return await GetJsonAsync<Notification>($"{Apiurl}/{notificationId}");
}
public async Task<Notification> AddNotificationAsync(Notification notification)
@ -43,12 +37,12 @@ namespace Oqtane.Services
public async Task<Notification> UpdateNotificationAsync(Notification notification)
{
return await PutJsonAsync<Notification>($"{Apiurl}/{notification.NotificationId.ToString()}", notification);
return await PutJsonAsync<Notification>($"{Apiurl}/{notification.NotificationId}", notification);
}
public async Task DeleteNotificationAsync(int notificationId)
{
await DeleteAsync($"{Apiurl}/{notificationId.ToString()}");
await DeleteAsync($"{Apiurl}/{notificationId}");
}
}
}

View File

@ -2,29 +2,15 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
using System.Linq;
namespace Oqtane.Services
{
public class PackageService : ServiceBase, IPackageService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
{
public PackageService(HttpClient http) : base(http) { }
public PackageService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Package"); }
}
private string Apiurl => CreateApiUrl("Package");
public async Task<List<Package>> GetPackagesAsync(string tag)
{

View File

@ -1,7 +1,6 @@
using Oqtane.Models;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
namespace Oqtane.Services
@ -10,28 +9,22 @@ namespace Oqtane.Services
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public PageModuleService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
{
public PageModuleService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "PageModule"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "PageModule");
public async Task<PageModule> GetPageModuleAsync(int pageModuleId)
{
return await GetJsonAsync<PageModule>($"{Apiurl}/{pageModuleId.ToString()}");
return await GetJsonAsync<PageModule>($"{Apiurl}/{pageModuleId}");
}
public async Task<PageModule> GetPageModuleAsync(int pageId, int moduleId)
{
return await GetJsonAsync<PageModule>($"{Apiurl}/{pageId.ToString()}/{moduleId.ToString()}");
return await GetJsonAsync<PageModule>($"{Apiurl}/{pageId}/{moduleId}");
}
public async Task<PageModule> AddPageModuleAsync(PageModule pageModule)
@ -41,17 +34,17 @@ namespace Oqtane.Services
public async Task<PageModule> UpdatePageModuleAsync(PageModule pageModule)
{
return await PutJsonAsync<PageModule>($"{Apiurl}/{pageModule.PageModuleId.ToString()}", pageModule);
return await PutJsonAsync<PageModule>($"{Apiurl}/{pageModule.PageModuleId}", pageModule);
}
public async Task UpdatePageModuleOrderAsync(int pageId, string pane)
{
await PutAsync($"{Apiurl}/?pageid={pageId.ToString()}&pane={pane}");
await PutAsync($"{Apiurl}/?pageid={pageId}&pane={pane}");
}
public async Task DeletePageModuleAsync(int pageModuleId)
{
await DeleteAsync($"{Apiurl}/{pageModuleId.ToString()}");
await DeleteAsync($"{Apiurl}/{pageModuleId}");
}
}
}

View File

@ -2,7 +2,6 @@
using System.Threading.Tasks;
using System.Linq;
using System.Net.Http;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
using System;
@ -14,42 +13,37 @@ namespace Oqtane.Services
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public PageService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public PageService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Page"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Page");
public async Task<List<Page>> GetPagesAsync(int siteId)
{
List<Page> pages = await GetJsonAsync<List<Page>>($"{Apiurl}?siteid={siteId.ToString()}");
List<Page> pages = await GetJsonAsync<List<Page>>($"{Apiurl}?siteid={siteId}");
pages = GetPagesHierarchy(pages);
return pages;
}
public async Task<Page> GetPageAsync(int pageId)
{
return await GetJsonAsync<Page>($"{Apiurl}/{pageId.ToString()}");
return await GetJsonAsync<Page>($"{Apiurl}/{pageId}");
}
public async Task<Page> GetPageAsync(int pageId, int userId)
{
return await GetJsonAsync<Page>($"{Apiurl}/{pageId.ToString()}?userid={userId.ToString()}");
return await GetJsonAsync<Page>($"{Apiurl}/{pageId}?userid={userId}");
}
public async Task<Page> GetPageAsync(string path, int siteId)
{
try
{
return await GetJsonAsync<Page>($"{Apiurl}/path/{siteId.ToString()}?path={WebUtility.UrlEncode(path)}");
return await GetJsonAsync<Page>($"{Apiurl}/path/{siteId}?path={WebUtility.UrlEncode(path)}");
}
catch
{
@ -64,12 +58,12 @@ namespace Oqtane.Services
public async Task<Page> AddPageAsync(int pageId, int userId)
{
return await PostJsonAsync<Page>($"{Apiurl}/{pageId.ToString()}?userid={userId.ToString()}", null);
return await PostJsonAsync<Page>($"{Apiurl}/{pageId}?userid={userId}", null);
}
public async Task<Page> UpdatePageAsync(Page page)
{
return await PutJsonAsync<Page>($"{Apiurl}/{page.PageId.ToString()}", page);
return await PutJsonAsync<Page>($"{Apiurl}/{page.PageId}", page);
}
public async Task UpdatePageOrderAsync(int siteId, int pageId, int? parentId)
@ -77,12 +71,12 @@ namespace Oqtane.Services
var parent = parentId == null
? string.Empty
: parentId.ToString();
await PutAsync($"{Apiurl}/?siteid={siteId.ToString()}&pageid={pageId.ToString()}&parentid={parent}");
await PutAsync($"{Apiurl}/?siteid={siteId}&pageid={pageId}&parentid={parent}");
}
public async Task DeletePageAsync(int pageId)
{
await DeleteAsync($"{Apiurl}/{pageId.ToString()}");
await DeleteAsync($"{Apiurl}/{pageId}");
}
private static List<Page> GetPagesHierarchy(List<Page> pages)

View File

@ -2,7 +2,6 @@
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
@ -12,29 +11,23 @@ namespace Oqtane.Services
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public ProfileService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
{
public ProfileService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Profile"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Profile");
public async Task<List<Profile>> GetProfilesAsync(int siteId)
{
List<Profile> profiles = await GetJsonAsync<List<Profile>>($"{Apiurl}?siteid={siteId.ToString()}");
List<Profile> profiles = await GetJsonAsync<List<Profile>>($"{Apiurl}?siteid={siteId}");
return profiles.OrderBy(item => item.ViewOrder).ToList();
}
public async Task<Profile> GetProfileAsync(int profileId)
{
return await GetJsonAsync<Profile>($"{Apiurl}/{profileId.ToString()}");
return await GetJsonAsync<Profile>($"{Apiurl}/{profileId}");
}
public async Task<Profile> AddProfileAsync(Profile profile)
@ -44,11 +37,11 @@ namespace Oqtane.Services
public async Task<Profile> UpdateProfileAsync(Profile profile)
{
return await PutJsonAsync<Profile>($"{Apiurl}/{profile.SiteId.ToString()}", profile);
return await PutJsonAsync<Profile>($"{Apiurl}/{profile.SiteId}", profile);
}
public async Task DeleteProfileAsync(int profileId)
{
await DeleteAsync($"{Apiurl}/{profileId.ToString()}");
await DeleteAsync($"{Apiurl}/{profileId}");
}
}
}

View File

@ -2,7 +2,6 @@
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
@ -12,29 +11,24 @@ namespace Oqtane.Services
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public RoleService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public RoleService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Role"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Role");
public async Task<List<Role>> GetRolesAsync(int siteId)
{
List<Role> roles = await GetJsonAsync<List<Role>>($"{Apiurl}?siteid={siteId.ToString()}");
List<Role> roles = await GetJsonAsync<List<Role>>($"{Apiurl}?siteid={siteId}");
return roles.OrderBy(item => item.Name).ToList();
}
public async Task<Role> GetRoleAsync(int roleId)
{
return await GetJsonAsync<Role>($"{Apiurl}/{roleId.ToString()}");
return await GetJsonAsync<Role>($"{Apiurl}/{roleId}");
}
public async Task<Role> AddRoleAsync(Role role)
@ -44,11 +38,11 @@ namespace Oqtane.Services
public async Task<Role> UpdateRoleAsync(Role role)
{
return await PutJsonAsync<Role>($"{Apiurl}/{role.RoleId.ToString()}", role);
return await PutJsonAsync<Role>($"{Apiurl}/{role.RoleId}", role);
}
public async Task DeleteRoleAsync(int roleId)
{
await DeleteAsync($"{Apiurl}/{roleId.ToString()}");
await DeleteAsync($"{Apiurl}/{roleId}");
}
}
}

View File

@ -17,7 +17,6 @@ namespace Oqtane.Services
_http = client;
}
protected async Task GetAsync(string uri)
{
var response = await _http.GetAsync(uri);
@ -83,7 +82,6 @@ namespace Oqtane.Services
var result = await response.Content.ReadFromJsonAsync<TResult>();
return result;
}
return default;
}
@ -122,6 +120,8 @@ namespace Oqtane.Services
if (response.StatusCode != HttpStatusCode.NoContent && response.StatusCode != HttpStatusCode.NotFound)
{
//TODO: Log errors here
Console.WriteLine($"Request: {response.RequestMessage.RequestUri}");
Console.WriteLine($"Response status: {response.StatusCode} {response.ReasonPhrase}");
}
@ -135,24 +135,31 @@ namespace Oqtane.Services
//TODO Missing content JSON validation
}
public static string CreateApiUrl(Alias alias, string absoluteUri, string serviceName)
// create an API Url which is tenant agnostic ( for use during installation )
public string CreateApiUrl(string serviceName)
{
Uri uri = new Uri(absoluteUri);
return CreateApiUrl(null, serviceName);
}
// create an API Url which is tenant aware ( for use with repositories )
public string CreateApiUrl(Alias alias, string serviceName)
{
string apiurl = "/";
if (Alias != null)
{
alias = Alias; // override the default alias ( for cross-tenant service calls )
}
string apiurl;
if (alias != null)
{
// build a url which passes the alias that may include a subfolder for multi-tenancy
apiurl = $"{uri.Scheme}://{alias.Name}/";
if (alias.Path == string.Empty)
{
apiurl += "~/";
}
// include the alias for multi-tenant context
apiurl += $"{alias.AliasId}/";
}
else
{
// build a url which ignores any subfolder for multi-tenancy
apiurl = $"{uri.Scheme}://{uri.Authority}/~/";
// tenant agnostic
apiurl += "~/";
}
apiurl += $"api/{serviceName}";
@ -160,15 +167,14 @@ namespace Oqtane.Services
return apiurl;
}
public static string CreateCrossTenantUrl(string url, Alias alias)
{
if (alias != null)
{
url += (url.Contains("?")) ? "&" : "?";
url += "aliasid=" + alias.AliasId.ToString();
}
// can be used to override the default alias
public Alias Alias { get; set; }
return url;
[Obsolete("This method is obsolete. Use CreateApiUrl(Alias alias, string serviceName) instead.", false)]
public string CreateApiUrl(Alias alias, string absoluteUri, string serviceName)
{
// only retained for short term backward compatibility
return CreateApiUrl(alias, serviceName);
}
}
}

View File

@ -1,8 +1,8 @@
using Oqtane.Models;
using System;
using Oqtane.Models;
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
@ -12,20 +12,13 @@ namespace Oqtane.Services
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public SettingService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
{
public SettingService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Setting"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Setting");
public async Task<Dictionary<string, string>> GetTenantSettingsAsync()
{
return await GetSettingsAsync(EntityNames.Tenant, -1);
@ -99,7 +92,7 @@ namespace Oqtane.Services
public async Task<Dictionary<string, string>> GetSettingsAsync(string entityName, int entityId)
{
var dictionary = new Dictionary<string, string>();
var settings = await GetJsonAsync<List<Setting>>($"{Apiurl}?entityname={entityName}&entityid={entityId.ToString()}");
var settings = await GetJsonAsync<List<Setting>>($"{Apiurl}?entityname={entityName}&entityid={entityId}");
foreach(Setting setting in settings.OrderBy(item => item.SettingName).ToList())
{
@ -110,11 +103,11 @@ namespace Oqtane.Services
public async Task UpdateSettingsAsync(Dictionary<string, string> settings, string entityName, int entityId)
{
var settingsList = await GetJsonAsync<List<Setting>>($"{Apiurl}?entityname={entityName}&entityid={entityId.ToString()}");
var settingsList = await GetJsonAsync<List<Setting>>($"{Apiurl}?entityname={entityName}&entityid={entityId}");
foreach (KeyValuePair<string, string> kvp in settings)
{
Setting setting = settingsList.FirstOrDefault(item => item.SettingName == kvp.Key);
Setting setting = settingsList.FirstOrDefault(item => item.SettingName.Equals(kvp.Key,StringComparison.OrdinalIgnoreCase));
if (setting == null)
{
setting = new Setting();
@ -138,7 +131,7 @@ namespace Oqtane.Services
public async Task<Setting> GetSettingAsync(int settingId)
{
return await GetJsonAsync<Setting>($"{Apiurl}/{settingId.ToString()}");
return await GetJsonAsync<Setting>($"{Apiurl}/{settingId}");
}
public async Task<Setting> AddSettingAsync(Setting setting)
@ -148,12 +141,12 @@ namespace Oqtane.Services
public async Task<Setting> UpdateSettingAsync(Setting setting)
{
return await PutJsonAsync<Setting>($"{Apiurl}/{setting.SettingId.ToString()}", setting);
return await PutJsonAsync<Setting>($"{Apiurl}/{setting.SettingId}", setting);
}
public async Task DeleteSettingAsync(int settingId)
{
await DeleteAsync($"{Apiurl}/{settingId.ToString()}");
await DeleteAsync($"{Apiurl}/{settingId}");
}

View File

@ -2,7 +2,6 @@
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
@ -12,44 +11,44 @@ namespace Oqtane.Services
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public SiteService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public SiteService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
private string Apiurl => CreateApiUrl(_siteState.Alias, "Site");
public void SetAlias(Alias alias)
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Site"); }
base.Alias = alias;
}
public async Task<List<Site>> GetSitesAsync(Alias alias)
public async Task<List<Site>> GetSitesAsync()
{
List<Site> sites = await GetJsonAsync<List<Site>>(CreateCrossTenantUrl(Apiurl, alias));
List<Site> sites = await GetJsonAsync<List<Site>>(Apiurl);
return sites.OrderBy(item => item.Name).ToList();
}
public async Task<Site> GetSiteAsync(int siteId, Alias alias)
public async Task<Site> GetSiteAsync(int siteId)
{
return await GetJsonAsync<Site>(CreateCrossTenantUrl($"{Apiurl}/{siteId.ToString()}", alias));
return await GetJsonAsync<Site>($"{Apiurl}/{siteId}");
}
public async Task<Site> AddSiteAsync(Site site, Alias alias)
public async Task<Site> AddSiteAsync(Site site)
{
return await PostJsonAsync<Site>(CreateCrossTenantUrl(Apiurl, alias), site);
return await PostJsonAsync<Site>(Apiurl, site);
}
public async Task<Site> UpdateSiteAsync(Site site, Alias alias)
public async Task<Site> UpdateSiteAsync(Site site)
{
return await PutJsonAsync<Site>(CreateCrossTenantUrl($"{Apiurl}/{site.SiteId.ToString()}", alias), site);
return await PutJsonAsync<Site>($"{Apiurl}/{site.SiteId}", site);
}
public async Task DeleteSiteAsync(int siteId, Alias alias)
public async Task DeleteSiteAsync(int siteId)
{
await DeleteAsync(CreateCrossTenantUrl($"{Apiurl}/{siteId.ToString()}", alias));
await DeleteAsync($"{Apiurl}/{siteId}");
}
}
}

View File

@ -3,28 +3,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class SiteTemplateService : ServiceBase, ISiteTemplateService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public SiteTemplateService(HttpClient http) : base(http) { }
public SiteTemplateService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "SiteTemplate"); }
}
private string Apiurl => CreateApiUrl("SiteTemplate");
public async Task<List<SiteTemplate>> GetSiteTemplatesAsync()
{

View File

@ -1,30 +1,20 @@
using Oqtane.Models;
using Oqtane.Shared;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
using System.Collections.Generic;
using System.Linq;
namespace Oqtane.Services
{
public class SqlService : ServiceBase, ISqlService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public SqlService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public SqlService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Sql"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Sql");
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
{

View File

@ -1,28 +1,14 @@
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
using System.Collections.Generic;
namespace Oqtane.Services
{
public class SystemService : ServiceBase, ISystemService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public SystemService(HttpClient http) : base(http) { }
public SystemService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "System"); }
}
private string Apiurl => CreateApiUrl("System");
public async Task<Dictionary<string, string>> GetSystemInfoAsync()
{

View File

@ -1,30 +1,22 @@
using Oqtane.Models;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
using System.Collections.Generic;
using System.Linq;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class TenantService : ServiceBase, ITenantService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public TenantService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public TenantService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Tenant"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "Tenant");
public async Task<List<Tenant>> GetTenantsAsync()
{
@ -34,7 +26,7 @@ namespace Oqtane.Services
public async Task<Tenant> GetTenantAsync(int tenantId)
{
return await GetJsonAsync<Tenant>($"{Apiurl}/{tenantId.ToString()}");
return await GetJsonAsync<Tenant>($"{Apiurl}/{tenantId}");
}
public async Task<Tenant> AddTenantAsync(Tenant tenant)
@ -44,12 +36,12 @@ namespace Oqtane.Services
public async Task<Tenant> UpdateTenantAsync(Tenant tenant)
{
return await PutJsonAsync<Tenant>($"{Apiurl}/{tenant.TenantId.ToString()}", tenant);
return await PutJsonAsync<Tenant>($"{Apiurl}/{tenant.TenantId}", tenant);
}
public async Task DeleteTenantAsync(int tenantId)
{
await DeleteAsync($"{Apiurl}/{tenantId.ToString()}");
await DeleteAsync($"{Apiurl}/{tenantId}");
}
}
}

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using System.Reflection;
using System;
using Oqtane.Shared;
@ -13,51 +12,17 @@ namespace Oqtane.Services
public class ThemeService : ServiceBase, IThemeService
{
private readonly HttpClient _http;
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public ThemeService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public ThemeService(HttpClient http) : base(http)
{
_http = http;
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "Theme"); }
}
private string Apiurl => CreateApiUrl("Theme");
public async Task<List<Theme>> GetThemesAsync()
{
List<Theme> themes = await GetJsonAsync<List<Theme>>(Apiurl);
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Theme theme in themes)
{
if (theme.Dependencies != "")
{
foreach (string dependency in theme.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
string assemblyname = dependency.Replace(".dll", "");
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{assemblyname}.dll");
Assembly.Load(bytes);
}
}
}
if (assemblies.Where(item => item.FullName.StartsWith(theme.AssemblyName + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{theme.AssemblyName}.dll");
Assembly.Load(bytes);
}
}
return themes.OrderBy(item => item.Name).ToList();
}

View File

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
namespace Oqtane.Services
@ -11,28 +10,22 @@ namespace Oqtane.Services
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public UserRoleService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
{
public UserRoleService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "UserRole"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "UserRole");
public async Task<List<UserRole>> GetUserRolesAsync(int siteId)
{
return await GetJsonAsync<List<UserRole>>($"{Apiurl}?siteid={siteId.ToString()}");
return await GetJsonAsync<List<UserRole>>($"{Apiurl}?siteid={siteId}");
}
public async Task<UserRole> GetUserRoleAsync(int userRoleId)
{
return await GetJsonAsync<UserRole>($"{Apiurl}/{userRoleId.ToString()}");
return await GetJsonAsync<UserRole>($"{Apiurl}/{userRoleId}");
}
public async Task<UserRole> AddUserRoleAsync(UserRole userRole)
@ -42,12 +35,12 @@ namespace Oqtane.Services
public async Task<UserRole> UpdateUserRoleAsync(UserRole userRole)
{
return await PutJsonAsync<UserRole>($"{Apiurl}/{userRole.UserRoleId.ToString()}", userRole);
return await PutJsonAsync<UserRole>($"{Apiurl}/{userRole.UserRoleId}", userRole);
}
public async Task DeleteUserRoleAsync(int userRoleId)
{
await DeleteAsync($"{Apiurl}/{userRoleId.ToString()}");
await DeleteAsync($"{Apiurl}/{userRoleId}");
}
}
}

View File

@ -1,7 +1,6 @@
using Oqtane.Shared;
using Oqtane.Models;
using System.Net.Http;
using Microsoft.AspNetCore.Components;
using System.Threading.Tasks;
namespace Oqtane.Services
@ -9,18 +8,13 @@ namespace Oqtane.Services
public class UserService : ServiceBase, IUserService
{
private readonly SiteState _siteState;
private readonly NavigationManager _navigationManager;
public UserService(HttpClient http, SiteState siteState, NavigationManager navigationManager) : base(http)
public UserService(HttpClient http, SiteState siteState) : base(http)
{
_siteState = siteState;
_navigationManager = navigationManager;
}
private string Apiurl
{
get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "User"); }
}
private string Apiurl => CreateApiUrl(_siteState.Alias, "User");
public async Task<User> GetUserAsync(int userId, int siteId)
{
@ -37,11 +31,6 @@ namespace Oqtane.Services
return await PostJsonAsync<User>(Apiurl, user);
}
public async Task<User> AddUserAsync(User user, Alias alias)
{
return await PostJsonAsync<User>(CreateCrossTenantUrl(Apiurl, alias), user);
}
public async Task<User> UpdateUserAsync(User user)
{
return await PutJsonAsync<User>($"{Apiurl}/{user.UserId}", user);

View File

@ -2,7 +2,9 @@
@inherits ContainerBase
<div class="container">
<div class="row px-4">
<ModuleActions /><h2><ModuleTitle /></h2>
<div class="d-flex flex-nowrap">
<ModuleActions /><h2><ModuleTitle /></h2>
</div>
<hr class="app-rule" />
</div>
<div class="row px-4">

Some files were not shown because too many files have changed in this diff Show More