Compare commits

..

2118 Commits

Author SHA1 Message Date
Shaun Walker
6db5c924c7 Merge pull request #5929 from oqtane/master
10.0.3 Release
2025-12-24 20:51:33 -05:00
Shaun Walker
51aecacee6 Merge pull request #5928 from oqtane/dev
10.0.3 Release
2025-12-24 20:51:14 -05:00
Shaun Walker
b3b8febd12 Update README.md 2025-12-24 20:49:25 -05:00
Shaun Walker
7c770d9a9d Merge pull request #5927 from sbwalker/dev
update azuredeploy.json
2025-12-24 20:47:58 -05:00
sbwalker
30b89fe56f update azuredeploy.json 2025-12-24 20:47:42 -05:00
Shaun Walker
06870f2577 Merge pull request #5926 from sbwalker/dev
fix migrations
2025-12-24 20:37:42 -05:00
sbwalker
e84170b8ea fix migrations 2025-12-24 20:37:25 -05:00
Shaun Walker
e8d26b2cb2 Merge pull request #5924 from sbwalker/dev
fix upgrade issue and increment version to 10.0.3
2025-12-24 19:34:43 -05:00
sbwalker
a8f87ea572 fix upgrade issue and increment version to 10.0.3 2025-12-24 19:34:24 -05:00
Shaun Walker
1fb78a457f Merge pull request #5921 from oqtane/master
10.0.2 Release
2025-12-23 13:21:30 -05:00
Shaun Walker
82cb7a8c02 Merge pull request #5920 from oqtane/dev
10.0.2 Release
2025-12-23 13:21:11 -05:00
Shaun Walker
cae61ab701 Update README.md 2025-12-23 13:20:09 -05:00
Shaun Walker
975c1955f2 Merge pull request #5919 from sbwalker/dev
update azuredeploy version
2025-12-23 13:16:27 -05:00
sbwalker
fc2a8cb9dd update azuredeploy version 2025-12-23 13:16:12 -05:00
Shaun Walker
e2d9aaaa0f Merge pull request #5918 from sbwalker/dev
fix #5916 - PostgreSQL failing to install on .NET 10
2025-12-23 12:09:35 -05:00
sbwalker
aca70dd6c7 fix #5916 - PostgreSQL failing to install on .NET 10 2025-12-23 12:09:16 -05:00
Shaun Walker
5a1b3a7017 Merge pull request #5915 from sbwalker/dev
synchronize static assets with .NET MAUI
2025-12-22 16:04:17 -05:00
sbwalker
6733299290 synchronize static assets with .NET MAUI 2025-12-22 16:04:00 -05:00
Shaun Walker
e11e021750 Merge pull request #5914 from sbwalker/dev
add ability for menu component to support arbitrary attributes
2025-12-22 08:38:06 -05:00
sbwalker
0ad5bd2335 add ability for menu component to support arbitrary attributes 2025-12-22 08:37:45 -05:00
Shaun Walker
255764a4ac Merge pull request #5912 from zyhfish/task/fix-5911
Fix #5911: let redirect to mapped url works in load balance env.
2025-12-22 07:41:16 -05:00
Ben
7330d5b2a7 Fix #5911: let redirect to mapped url works in load balance env. 2025-12-22 15:17:40 +08:00
Shaun Walker
5d3e507672 Merge pull request #5906 from sbwalker/dev
bump version to 10.0.2
2025-12-19 15:51:37 -05:00
sbwalker
15ee2c9bcb bump version to 10.0.2 2025-12-19 15:51:21 -05:00
Shaun Walker
e1163b7ab1 Merge pull request #5905 from sbwalker/dev
allow menu component to be extensible
2025-12-19 15:35:52 -05:00
sbwalker
96bea78424 allow menu component to be extensible 2025-12-19 15:35:35 -05:00
Shaun Walker
8ba67a63ba Merge pull request #5904 from sbwalker/dev
add url mapping referrer
2025-12-19 15:06:22 -05:00
sbwalker
8120db84f4 add url mapping referrer 2025-12-19 15:06:06 -05:00
Shaun Walker
4e6a6afaab Merge pull request #5903 from sbwalker/dev
expand size of page name
2025-12-19 14:26:03 -05:00
sbwalker
417a6bf226 expand size of page name 2025-12-19 14:25:44 -05:00
Shaun Walker
5e5d91bd93 Merge pull request #5902 from sbwalker/dev
handle case sensitivity for entity names and permission names
2025-12-19 10:56:32 -05:00
sbwalker
5c536aafc2 handle case sensitivity for entity names and permission names 2025-12-19 10:56:08 -05:00
Shaun Walker
15efe75aa8 Merge pull request #5901 from sbwalker/dev
fix #5897 - allow SQLite to drop columns, remove deprecated columns, and handle upgrade logic
2025-12-19 09:04:14 -05:00
sbwalker
a10575bfc3 fix #5897 - allow SQLite to drop columns, remove deprecated columns, and handle upgrade logic 2025-12-19 09:03:44 -05:00
Shaun Walker
57e26d6156 Merge pull request #5899 from sbwalker/dev
login improvements
2025-12-18 16:01:05 -05:00
sbwalker
1682a123b4 login improvements 2025-12-18 16:00:46 -05:00
Shaun Walker
13064cdb26 Merge pull request #5895 from sbwalker/dev
enable EnhancedNavigation by default
2025-12-17 15:51:38 -05:00
sbwalker
f74eda274a enable EnhancedNavigation by default 2025-12-17 15:51:21 -05:00
Shaun Walker
7dee55ce30 Merge pull request #5892 from sbwalker/dev
module migration issues should not prevent the framework from starting up
2025-12-16 14:34:03 -05:00
sbwalker
8113c82da8 module migration issues should not prevent the framework from starting up 2025-12-16 14:33:42 -05:00
Shaun Walker
2d684d23d7 Merge pull request #5887 from oqtane/master
Merge pull request #5886 from oqtane/dev
2025-12-15 14:06:20 -05:00
Shaun Walker
33da5809e3 Merge pull request #5886 from oqtane/dev
10.0.1 Release
2025-12-15 14:05:48 -05:00
Shaun Walker
68a6e6862e Update README.md 2025-12-15 14:02:25 -05:00
Shaun Walker
07fb15d5be Merge pull request #5885 from sbwalker/dev
update azuredeploy.json
2025-12-15 13:59:47 -05:00
sbwalker
0f791253ba update azuredeploy.json 2025-12-15 13:59:30 -05:00
Shaun Walker
828d070194 Merge pull request #5884 from sbwalker/dev
increase width of login component
2025-12-15 11:29:09 -05:00
sbwalker
0d5bb3f3b3 increase width of login component 2025-12-15 11:28:51 -05:00
Shaun Walker
32de1ca511 Merge pull request #5883 from sbwalker/dev
limit management of user settings to host users
2025-12-15 11:16:57 -05:00
sbwalker
f5f00c51c1 limit management of user settings to host users 2025-12-15 11:16:37 -05:00
Shaun Walker
1305125390 Merge pull request #5882 from sbwalker/dev
remove unnecessary comment
2025-12-15 10:47:40 -05:00
sbwalker
c539f41ebf remove unnecessary comment 2025-12-15 10:47:01 -05:00
Shaun Walker
075e754830 Merge pull request #5881 from sbwalker/dev
use EmailConfirmationToken (which is valid for 10 minutes)
2025-12-15 10:43:28 -05:00
sbwalker
87fd9dd000 use EmailConfirmationToken (which is valid for 10 minutes) 2025-12-15 10:43:11 -05:00
Shaun Walker
e34321f727 Merge pull request #5880 from sbwalker/dev
improve new API method signatures
2025-12-15 10:29:22 -05:00
sbwalker
a48dff4a85 improve new API method signatures 2025-12-15 10:29:03 -05:00
Shaun Walker
576d3d0b56 Merge pull request #5879 from sbwalker/dev
relocate the GetUser() call in App.razor so that it is not included in the Site cache
2025-12-15 09:10:41 -05:00
sbwalker
640c2cee00 Merge branch 'dev' of https://github.com/sbwalker/oqtane.framework into dev 2025-12-15 09:02:32 -05:00
sbwalker
1958787185 relocate the GetUser() call in App.razor so that it is not included in the Site cache 2025-12-15 09:02:25 -05:00
Shaun Walker
073e1ac13a Merge pull request #5876 from leigh-pointer/CurrentPageUser
Add pagination state to Pager in Index.razor
2025-12-15 08:25:24 -05:00
Shaun Walker
c0eacd0d6b Merge pull request #5878 from sbwalker/dev
refactor new Forgot Username and Login Link methods
2025-12-15 08:24:36 -05:00
sbwalker
7938eaf123 refactor new Forgot Username and Login Link methods 2025-12-15 08:23:41 -05:00
Leigh Pointer
b4f8896713 Add pagination state to Pager in Index.razor
When clicking the Roles or Edit button, returning would load the first page.
Pager now tracks and updates the current page using a new _page field and the CurrentPage/OnPageChange parameters. This improves pagination handling and user experience by persisting the current page state.
2025-12-15 10:21:32 +01:00
Shaun Walker
c418ddf240 Merge pull request #5875 from sbwalker/dev
use a more complex token for login links
2025-12-14 17:08:45 -05:00
sbwalker
6c6b36f3da use a more complex token for login links 2025-12-14 17:08:19 -05:00
Shaun Walker
c0c71251ab Merge pull request #5873 from leigh-pointer/SupportCustomRole
Enhance tab authorization with role and permission checks #5872
2025-12-14 15:15:19 -05:00
Shaun Walker
2685c18798 Merge pull request #5871 from leigh-pointer/AltText
Add AltText/title support to ActionDialog and ActionLink
2025-12-14 15:15:03 -05:00
Shaun Walker
7f914271ed Merge pull request #5870 from leigh-pointer/RendarBoundry
Add null checks for RenderModeBoundary in ModuleBase methods
2025-12-14 15:14:44 -05:00
Shaun Walker
7b37cc3c82 Merge pull request #5874 from sbwalker/dev
added support for Forgot Username and Use Login Link
2025-12-14 15:14:25 -05:00
sbwalker
ec2afd5f03 added support for Forgot Username and Use Login Link 2025-12-14 15:13:53 -05:00
Leigh Pointer
e62268af2e Update TabStrip.razor
The authorization flow is:
•	Host tabs: Only Host (Admin blocked by Step 1)
•	Everything else: Admin bypasses, others check permissions
2025-12-13 21:56:05 +01:00
Leigh Pointer
01ad99b925 Enhance tab authorization with role and permission checks #5872
Add RoleName and PermissionName parameters to TabPanel for fine-grained tab visibility control. Update IsAuthorized logic in TabStrip to prioritize Host/Admin access, then check SecurityAccessLevel, and additionally require specified roles or permissions if provided. Removes redundant Admin/Host checks from the switch statement for clarity.
2025-12-13 18:13:37 +01:00
Leigh Pointer
a33e9d25cc Add AltText/title support to ActionDialog and ActionLink
Introduce optional AltText parameter to ActionDialog and ActionLink components. AltText is now used as the title attribute on rendered buttons and links, providing tooltips for improved accessibility and user experience. All relevant elements, including those in disabled states, now support this enhancement.
2025-12-13 13:04:30 +01:00
Leigh Pointer
a0e45cbea0 Add null checks for RenderModeBoundary in ModuleBase methods
Add null checks to key ModuleBase methods to ensure RenderModeBoundary is available before use. Throw a detailed InvalidOperationException with guidance if it is missing, improving error handling and developer feedback.
2025-12-13 12:55:24 +01:00
Shaun Walker
171314947c Merge pull request #5869 from sbwalker/dev
add null check for User
2025-12-12 15:57:07 -05:00
sbwalker
6b883b3f94 add null check for User 2025-12-12 15:56:50 -05:00
Shaun Walker
c99348650f Merge pull request #5867 from sbwalker/dev
admin dashboard should always use enhanced navigation
2025-12-11 19:29:10 -05:00
sbwalker
011375a081 admin dashboard should always use enhanced navigation 2025-12-11 19:28:50 -05:00
Shaun Walker
38f43c9988 Merge pull request #5866 from sbwalker/dev
update version in Oqtane Application Template nuspec
2025-12-11 15:51:43 -05:00
sbwalker
f459d0503a update version in Oqtane Application Template nuspec 2025-12-11 15:51:27 -05:00
Shaun Walker
c2912a291e Merge pull request #5865 from sbwalker/dev
bump Oqtane version to 10.0.1
2025-12-11 15:27:00 -05:00
sbwalker
53a88e0c9f bump Oqtane version to 10.0.1 2025-12-11 15:26:42 -05:00
Shaun Walker
9cf670bcad Merge pull request #5864 from sbwalker/dev
update nuspec files to .NET SDK 10.0.1
2025-12-11 15:14:01 -05:00
sbwalker
156e7bd3d4 update nuspec files to .NET SDK 10.0.1 2025-12-11 15:13:45 -05:00
Shaun Walker
009829c8f9 Merge pull request #5863 from sbwalker/dev
update to .NET SDK 10.0.1
2025-12-11 15:09:13 -05:00
sbwalker
d7c0b0aaaf update to .NET SDK 10.0.1 2025-12-11 15:08:52 -05:00
Shaun Walker
06071fb7f9 Merge pull request #5857 from sbwalker/dev
move user workload from siterouter to app component to improve performance and 404 handling
2025-12-05 08:40:57 -05:00
sbwalker
a51f87d743 move user workload from siterouter to app component to improve performance and 404 handling 2025-12-05 08:40:30 -05:00
Shaun Walker
12fa6ff4f0 Merge pull request #5855 from sbwalker/dev
remove unique index of TenantId and Name from Site table as site name does not need to be unique. Remove TenantId column from Site table as it is not necessary and should be obtained from the Alias.
2025-12-03 15:29:07 -05:00
sbwalker
23d14c62a5 remove unique index of TenantId and Name from Site table as site name does not need to be unique. Remove TenantId column from Site table as it is not necessary and should be obtained from the Alias. 2025-12-03 15:28:31 -05:00
Shaun Walker
ad993c6180 Merge pull request #5854 from leigh-pointer/refs
Package updates
2025-12-03 13:03:23 -05:00
Shaun Walker
e99ce3ac7b Merge pull request #5853 from zyhfish/task/fix-5852
Fix #5852: clear the cache after import content.
2025-12-03 13:03:04 -05:00
Leigh Pointer
270b447fbd Package updates
Radzen, Swashbuckle
Added the Bold tool to the Radzen editor.
2025-12-03 11:19:10 +01:00
Leigh Pointer
1c55a74ff1 Merge remote-tracking branch 'upstream/dev' into dev 2025-12-03 11:02:09 +01:00
Ben
47f42747cb clean the usage. 2025-12-03 09:09:43 +08:00
Ben
86a3f67871 Fix #5852: clear the cache after import content. 2025-12-03 09:08:01 +08:00
Shaun Walker
29b87f809f Merge pull request #5848 from W6HBR/dev
Fix SMTPRelay condition for sender email validation
2025-12-02 11:27:44 -05:00
Shaun Walker
8bd63fdc61 Merge pull request #5850 from zyhfish/task/fix-5849
Fix #5849: correct resources key.
2025-12-02 11:25:03 -05:00
Ben
cf88347c3d Fix #5849: correct resources key. 2025-12-02 09:23:43 +08:00
Jon Welfringer
171f9c84a0 Fix SMTPRelay condition for sender email validation
Prior change was leaving sender null and not properly setting "From" address when used in a relay configuration. This caused emails to go to the deleted state and not be delivered.
2025-12-01 16:36:19 -08:00
Shaun Walker
a6069e572d Merge pull request #5782 from zyhfish/task/display-missing-service-error
Display error message when missing injected services.
2025-12-01 15:45:28 -05:00
Shaun Walker
16a13a6c01 Merge pull request #5845 from Amazing-Software-Solutions/dev
Added Style Paramater to RichTextEditor
2025-12-01 15:45:17 -05:00
vnetonline
ac31cd3f41 Merge branch 'oqtane:dev' into dev 2025-11-29 15:12:07 +11:00
vnetonline
321fe2954e Added Style Paramater to RichTextEditor to remove the margin-bottom: 50px; if the developer wishes 2025-11-29 15:10:58 +11:00
Shaun Walker
e2f174e0b5 Merge pull request #5843 from sbwalker/dev
update to .NET 10 PostgreSQL provider
2025-11-25 14:50:00 -05:00
sbwalker
50c085fe65 update to .NET 10 PostgreSQL provider 2025-11-25 14:49:45 -05:00
Shaun Walker
4e63c9ce9d Merge pull request #5842 from sbwalker/dev
add Enhanced Navigation option in Site Settings
2025-11-25 14:44:10 -05:00
sbwalker
fb6e8bb233 add Enhanced Navigation option in Site Settings 2025-11-25 14:43:51 -05:00
Shaun Walker
44103c1311 Merge pull request #5840 from zyhfish/task/fix-5839
Fix #5839: do not send confirmation email  to deleted users.
2025-11-25 08:52:41 -05:00
Ben
6ef6e6aac8 Fix #5839: do not send confirmation email to deleted users. 2025-11-25 11:21:20 +08:00
Shaun Walker
9499012825 Merge pull request #5834 from leigh-pointer/baseNull
Update ReplaceTokens on ModuleBase
2025-11-24 10:18:59 -05:00
Shaun Walker
6af73873d7 Merge pull request #5837 from zyhfish/task/fix-5836
Fix #5836: update the setting by check existing first.
2025-11-24 10:18:47 -05:00
Ben
0a04035b2f Fix #5836: update the setting by check existing first. 2025-11-24 18:14:14 +08:00
Leigh Pointer
1e3c176ddf Update ReplaceTokens on ModuleBase
Check for Contents == null
2025-11-22 13:31:04 +01:00
Leigh Pointer
f5bb9a934c Merge remote-tracking branch 'upstream/dev' into dev 2025-11-22 13:26:18 +01:00
Shaun Walker
476cf7c080 Merge pull request #5832 from zyhfish/task/fix-5649
Fix #5649: handle not found request.
2025-11-21 10:26:59 -05:00
Ben
1279c30fbb Fix #5649: check path by internal api. 2025-11-21 18:34:22 +08:00
Ben
012b7ba6ed Fix #5649: handle not found request. 2025-11-20 19:03:26 +08:00
Shaun Walker
e08c033e76 Merge pull request #5831 from sbwalker/dev
initialize the Owner name when using an Oqtane Application and creating new modules or themes
2025-11-19 10:49:38 -05:00
sbwalker
dafbae7237 initialize the Owner name when using an Oqtane Application and creating new modules or themes 2025-11-19 10:47:38 -05:00
Shaun Walker
31b8080a3d Update README.md 2025-11-17 11:24:49 -05:00
Shaun Walker
28c7617227 Refine instructions for submitting pull requests 2025-11-17 11:22:40 -05:00
Shaun Walker
7f7c53dabe Fix command reference in README for uninstalling template
Corrected the command reference from .NERT to .NET CLI.
2025-11-17 11:20:47 -05:00
Shaun Walker
950a9bf2fa Update README.md 2025-11-17 11:20:08 -05:00
Shaun Walker
f0d4a416be Clarify cloning instructions for Oqtane repository
Updated instructions for cloning Oqtane source code.
2025-11-17 09:33:54 -05:00
Shaun Walker
708d79ffaf Fix filename extension in README for solution file 2025-11-17 09:29:45 -05:00
Shaun Walker
583bd3b511 Update README.md 2025-11-17 09:29:06 -05:00
Shaun Walker
5f8798c224 Merge pull request #5822 from oqtane/master
10.0.0 Release
2025-11-14 16:40:51 -05:00
Shaun Walker
74c259cd79 10.0.0 Release
10.0.0 Release
2025-11-14 16:40:29 -05:00
Shaun Walker
c96787f1b9 Update README.md 2025-11-14 16:38:56 -05:00
Shaun Walker
aaac471956 Merge pull request #5820 from sbwalker/dev
update azuredeploy
2025-11-14 16:33:11 -05:00
sbwalker
db41bfe638 update azuredeploy 2025-11-14 16:32:58 -05:00
Shaun Walker
bfc9acb170 Merge pull request #5819 from sbwalker/dev
use consistent folder names for external and internal templates
2025-11-14 14:27:55 -05:00
sbwalker
50540b50aa use consistent folder names for external and internal templates 2025-11-14 14:27:35 -05:00
Shaun Walker
9f9d3460b1 Merge pull request #5818 from sbwalker/dev
resolve issues with internal templates
2025-11-14 14:19:39 -05:00
sbwalker
e2f02bcd4b resolve issues with internal templates 2025-11-14 14:19:24 -05:00
Shaun Walker
538bc093e0 Merge pull request #5817 from sbwalker/dev
resolve UI issue for internal template
2025-11-14 13:58:50 -05:00
sbwalker
3d34ab83c6 resolve UI issue for internal template 2025-11-14 13:58:36 -05:00
Shaun Walker
5fb413505c Merge pull request #5816 from sbwalker/dev
improve help text for Owner field
2025-11-14 13:43:42 -05:00
sbwalker
efcbdee869 improve help text for Owner field 2025-11-14 13:43:25 -05:00
Shaun Walker
2ea6f9e447 Merge pull request #5815 from sbwalker/dev
improve module/theme creation UI to support internal/external scenarios
2025-11-14 13:35:36 -05:00
sbwalker
2acd5799d9 improve module/theme creation UI to support internal/external scenarios 2025-11-14 13:35:21 -05:00
Shaun Walker
78bfc91469 Merge pull request #5814 from sbwalker/dev
resolve naming issue for module/theme created from internal template
2025-11-14 13:24:08 -05:00
sbwalker
c9590247eb resolve naming issue for module/theme created from internal template 2025-11-14 13:23:55 -05:00
Shaun Walker
df4209ed77 Merge pull request #5813 from sbwalker/dev
fix typo in resource file
2025-11-14 13:01:51 -05:00
sbwalker
4daaaa8dbf fix typo in resource file 2025-11-14 13:01:37 -05:00
Shaun Walker
eb10f2a6a0 Merge pull request #5812 from sbwalker/dev
resolve UI issue in module/theme creation
2025-11-14 12:53:25 -05:00
sbwalker
05993ab462 resolve UI issue in module/theme creation 2025-11-14 12:53:10 -05:00
Shaun Walker
f276a892fd Merge pull request #5811 from sbwalker/dev
rename Application Template internal module/theme template manifests
2025-11-14 12:47:16 -05:00
sbwalker
7a7508c4ca rename Application Template internal module/theme template manifests 2025-11-14 12:47:01 -05:00
Shaun Walker
d2cf817aac Merge pull request #5810 from sbwalker/dev
allow module/theme template manifests to have custom names so that they do not conflict with .NET template.json
2025-11-14 12:44:01 -05:00
sbwalker
b9497cbb56 allow module/theme template manifests to have custom names so that they do not conflict with .NET template.json 2025-11-14 12:43:40 -05:00
Shaun Walker
b2aa17410e Merge pull request #5809 from sbwalker/dev
remove upgrade logic which removes Internal module/theme templates
2025-11-14 12:29:40 -05:00
sbwalker
545096a753 remove upgrade logic which removes Internal module/theme templates 2025-11-14 12:29:24 -05:00
Shaun Walker
d652757614 Merge pull request #5808 from sbwalker/dev
resolved issues in Oqtane Application Template in .NET 10
2025-11-14 12:22:22 -05:00
sbwalker
bff00832fc resolved issues in Oqtane Application Template in .NET 10 2025-11-14 12:22:02 -05:00
Shaun Walker
7a09a48b64 Merge pull request #5804 from sbwalker/dev
rolling back change to include _framework assets as it resolves the run-time issue but creates a build issue
2025-11-13 11:14:27 -05:00
sbwalker
c5fbb5b61b rolling back change to include _framework assets as it resolves the run-time issue but creates a build issue 2025-11-13 11:13:56 -05:00
Shaun Walker
f6be499e47 Merge pull request #5803 from sbwalker/dev
added _framework JS files to application template to resolve issue in .NET 10
2025-11-13 10:59:29 -05:00
sbwalker
49ef0d7464 added _framework JS files to application template to resolve issue in .NET 10 2025-11-13 10:59:01 -05:00
Leigh Pointer
528cbde7e5 Merge remote-tracking branch 'upstream/dev' into dev 2025-11-13 00:31:56 +01:00
Shaun Walker
cf7e082dbc Merge pull request #5800 from sbwalker/dev
fix compilation error caused by Microsoft.OpenApi
2025-11-12 11:00:12 -05:00
sbwalker
b786faa6a1 fix compilation error caused by Microsoft.OpenApi 2025-11-12 10:59:52 -05:00
Shaun Walker
ebbf39c360 Merge pull request #5799 from sbwalker/dev
removed System.Net.Http.Json depemdency based on pruning message during compilation
2025-11-12 08:41:53 -05:00
sbwalker
92dc46a81e removed System.Net.Http.Json depemdency based on pruning message during compilation 2025-11-12 08:41:28 -05:00
Shaun Walker
63494bc7ee Merge pull request #5796 from leigh-pointer/swsa
update Swashbuckle to 10.0.0
2025-11-12 08:04:25 -05:00
Leigh Pointer
e6ee13784f update Swashbuckle to 10.0.0
update Swashbuckle to 10.0.0 in csproj and nuspec
2025-11-12 12:12:03 +01:00
Leigh Pointer
11284f0285 Merge remote-tracking branch 'upstream/dev' into dev 2025-11-12 12:07:30 +01:00
Shaun Walker
0b2ade4b01 Merge pull request #5795 from sbwalker/dev
upgrade to final .NET 10 SDK
2025-11-11 14:15:49 -05:00
sbwalker
f687c09adc upgrade to final .NET 10 SDK 2025-11-11 14:15:24 -05:00
Shaun Walker
20fdd211be Merge pull request #5794 from sbwalker/dev
upgrade to final .NET 10 SDK
2025-11-11 14:11:06 -05:00
sbwalker
21fcd653b8 upgrade to final .NET 10 SDK 2025-11-11 14:10:41 -05:00
Shaun Walker
62db107d90 Merge pull request #5792 from tvatavuk/patch-4 2025-11-10 11:17:13 -05:00
Tonći Vatavuk
f6c1d65c89 Refactor includeScript to initialize script as null
fixes #5791
2025-11-10 14:00:02 +01:00
Shaun Walker
8f3c5f5768 Merge pull request #5786 from sbwalker/dev
update nuspec to match csproj
2025-11-07 18:22:44 -05:00
sbwalker
eb8cfa28ed update nuspec to match csproj 2025-11-07 18:22:27 -05:00
Shaun Walker
b4789dff3e Merge pull request #5783 from leigh-pointer/Refs
Update NuGet package versions for dependencies
2025-11-07 18:17:47 -05:00
Leigh Pointer
ee25c46ee1 Update NuGet package versions for dependencies
Update NuGet package versions for dependencies
Upgraded the following NuGet packages to newer versions:
- `SixLabors.ImageSharp` from `3.1.11` to `3.1.12`
- `HtmlAgilityPack` from `1.12.3` to `1.12.4`
- `Swashbuckle.AspNetCore` from `9.0.5` to `9.0.6`
- `MailKit` from `4.14.0` to `4.14.1`
- `EFCore.NamingConventions` from `9.0.0` to `10.0.0-rc.2`
- `Npgsql.EntityFrameworkCore.PostgreSQL` from `9.0.4` to `10.0.0-rc.2`
2025-11-07 13:15:29 +01:00
Leigh Pointer
dc9d4a1938 Merge remote-tracking branch 'upstream/dev' into dev 2025-11-07 12:57:35 +01:00
Ben
e58ee4e5b1 Display error message when missing injected services. 2025-11-07 14:40:14 +08:00
Shaun Walker
3c5d839e9d Merge pull request #5777 from sbwalker/dev
update application template config
2025-11-04 20:24:40 -05:00
sbwalker
590901bf6e update application template config 2025-11-04 20:24:21 -05:00
Shaun Walker
76938503b6 Merge pull request #5776 from sbwalker/dev
remove unused references
2025-11-04 20:15:44 -05:00
sbwalker
9ffd4f39e9 remove unused references 2025-11-04 20:15:25 -05:00
Shaun Walker
a707ae7da9 Merge pull request #5775 from zyhfish/task/fix-5774
Fix #5774: remove duplicated radzen dialog delegate handlers.
2025-11-04 11:13:30 -05:00
Ben
0e717c8f57 Fix #5774: remove duplicated radzen dialog delegate handlers. 2025-11-04 17:06:11 +08:00
Shaun Walker
78853173db Merge pull request #5771 from leigh-pointer/resizeEditors
Added Resizable css to text editors
2025-11-03 19:22:15 -05:00
Shaun Walker
20005797e5 Merge pull request #5773 from sbwalker/dev
Workaround for a .NET 10 RC2 publishing issue for Wasm projects
2025-11-03 19:21:58 -05:00
sbwalker
206806d01a Workaround for a .NET 10 RC2 publishing issue for Wasm projects 2025-11-03 19:21:37 -05:00
Leigh Pointer
2def6ad854 Added Resizable css to text editors
updated the app.css with resizable and applied the class to Radzen and Quilll text editors
2025-11-01 09:53:25 +01:00
Leigh Pointer
4339833aa3 Merge remote-tracking branch 'upstream/dev' into dev 2025-11-01 09:29:35 +01:00
Shaun Walker
afbe6c7054 Merge pull request #5769 from sbwalker/dev
fix solution file references
2025-10-31 15:57:04 -04:00
sbwalker
2914749253 fix solution file references 2025-10-31 15:56:48 -04:00
Shaun Walker
54902051ce Merge pull request #5767 from sbwalker/dev
fix #5735 - logout redirect on action components
2025-10-31 12:10:00 -04:00
sbwalker
01ee9650ff fix #5735 - logout redirect on action components 2025-10-31 12:09:37 -04:00
Shaun Walker
2f6b9a2fc7 Merge pull request #5765 from sbwalker/dev
remove MyModule and MyTheme from Application Template - solution can now be extended using Internal module/theme templates
2025-10-31 10:03:02 -04:00
sbwalker
20e270c040 remove MyModule and MyTheme from Application Template - solution can now nbe extended using Internal module/theme templates 2025-10-31 10:02:34 -04:00
Shaun Walker
afb2613f67 Merge pull request #5763 from sbwalker/dev
use new solution file format in module/theme template
2025-10-31 08:24:38 -04:00
sbwalker
b917a7bbf6 use new solution file format in module/theme template 2025-10-31 08:24:22 -04:00
Shaun Walker
7d01aa449e Merge pull request #5762 from sbwalker/dev
use new solution file in app template
2025-10-31 08:17:15 -04:00
sbwalker
fe16594885 use new solution file in app template 2025-10-31 08:16:59 -04:00
Shaun Walker
29f74131d1 Merge pull request #5761 from sbwalker/dev
use new solution file format
2025-10-31 08:13:03 -04:00
sbwalker
b0e861e985 use new solution file format 2025-10-31 08:09:39 -04:00
Shaun Walker
ed8df61143 Merge pull request #5759 from sbwalker/dev
migrate to new Visual Studio solution file
2025-10-30 16:57:43 -04:00
sbwalker
6374314d3c migrate to new Visual Studio solution file 2025-10-30 16:57:25 -04:00
Shaun Walker
aedfa91ce6 Merge pull request #5758 from sbwalker/dev
make logger public
2025-10-30 16:34:16 -04:00
sbwalker
087d5ef394 make logger public 2025-10-30 16:33:59 -04:00
Shaun Walker
637e285441 Merge pull request #5757 from sbwalker/dev
add passkey and login management to User Management
2025-10-30 11:09:13 -04:00
sbwalker
ab4bc7e678 add passkey and login management to User Management 2025-10-30 11:08:56 -04:00
Shaun Walker
e68fe3a9c3 Merge pull request #5756 from sbwalker/dev
create Security tab in User Management
2025-10-30 09:44:05 -04:00
sbwalker
adfd870319 create Security tab in User Management 2025-10-30 09:43:49 -04:00
Shaun Walker
edd89bf133 Merge pull request #5755 from sbwalker/dev
passkey adjustments
2025-10-30 09:15:55 -04:00
sbwalker
d774557522 passkey adjustments 2025-10-30 09:15:40 -04:00
Shaun Walker
f9c1906fe2 Merge pull request #5753 from sbwalker/dev
ensure Logins are site specific
2025-10-29 20:04:51 -04:00
sbwalker
d5ad29be34 ensure Logins are site specific 2025-10-29 20:04:35 -04:00
Shaun Walker
d62f8e966c Merge pull request #5752 from sbwalker/dev
improve documentation
2025-10-29 16:44:01 -04:00
sbwalker
670f3854fa improve documentation 2025-10-29 16:43:46 -04:00
Shaun Walker
ed4ab703c0 Merge pull request #5751 from sbwalker/dev
fix Settings update
2025-10-29 16:29:38 -04:00
sbwalker
1d3c1c158f fix Settings update 2025-10-29 16:29:21 -04:00
Shaun Walker
431fa05763 Merge pull request #5750 from sbwalker/dev
only display passkey login when connection is secure
2025-10-29 13:37:06 -04:00
sbwalker
cd24573599 only display passkey login when connection is secure 2025-10-29 13:36:49 -04:00
Shaun Walker
c43af46d38 Merge pull request #5749 from sbwalker/dev
add passkey functionality
2025-10-29 12:32:08 -04:00
sbwalker
7e69b5193f add passkey functionality 2025-10-29 12:31:50 -04:00
Leigh Pointer
a06b1becc5 Merge remote-tracking branch 'upstream/dev' into dev 2025-10-27 11:24:37 +01:00
Shaun Walker
b2dfde58d5 Merge pull request #5744 from sbwalker/dev
add passkey infrastructure
2025-10-23 12:46:53 -04:00
sbwalker
e548c21c94 add passkey infrastructure 2025-10-23 12:46:34 -04:00
Shaun Walker
f4a1bf659f Merge pull request #5743 from sbwalker/dev
hack to get Passkeys working
2025-10-22 16:40:09 -04:00
sbwalker
cf3a86dc4a hack to get Passkeys working 2025-10-22 16:39:52 -04:00
Shaun Walker
bbd441b0b7 Merge pull request #5742 from sbwalker/dev
preserve previous servicelifetime setting
2025-10-22 14:31:02 -04:00
sbwalker
ac9b7a60fd preserve previous servicelifetime setting 2025-10-22 14:30:47 -04:00
Shaun Walker
9abe4a1c42 Merge pull request #5741 from sbwalker/dev
refactor TenantDBContext to accomodate AspNetUserPasskeys
2025-10-22 14:06:30 -04:00
sbwalker
273097d96d refactor TenantDBContext to accomodate AspNetUserPasskeys 2025-10-22 14:06:15 -04:00
Shaun Walker
57aeac2277 Merge pull request #5740 from sbwalker/dev
consolidate interface and concrete class
2025-10-22 11:21:02 -04:00
sbwalker
39ad5a0638 consolidate interface and concrete class 2025-10-22 11:20:45 -04:00
Shaun Walker
b4ef5faa28 Merge pull request #5738 from sbwalker/dev
passkey changes
2025-10-21 16:41:16 -04:00
sbwalker
a4c2989062 passkey changes 2025-10-21 16:40:59 -04:00
Shaun Walker
2ef9963587 Merge pull request #5737 from sbwalker/dev
remove unnecessary using
2025-10-21 14:23:51 -04:00
sbwalker
19b003ae49 remove unnecessary using 2025-10-21 14:23:35 -04:00
Shaun Walker
5d66c904cd Merge pull request #5736 from sbwalker/dev
fix issue with image file list
2025-10-21 09:22:46 -04:00
sbwalker
ca521f3a5e fix issue with image file list 2025-10-21 09:22:29 -04:00
Shaun Walker
9a622dd88f Merge pull request #5734 from sbwalker/dev
reorganize user profile to prepare for pass keys
2025-10-20 16:23:17 -04:00
sbwalker
ff6c71e587 reorganize user profile to prepare for pass keys 2025-10-20 16:23:00 -04:00
Shaun Walker
7c3d59915e Merge pull request #5733 from sbwalker/dev
add AspNetUserPasskeys migration
2025-10-20 12:19:31 -04:00
sbwalker
970f6b400f add AspNetUserPasskeys migration 2025-10-20 12:19:17 -04:00
Shaun Walker
abc4905a14 Merge pull request #5731 from zyhfish/task/fix-5714
Fix #5714: update the default order of profile fields.
2025-10-20 11:58:35 -04:00
Shaun Walker
be3ecdf7f6 Merge pull request #5732 from sbwalker/dev
fix #5671 - copy page and module settings from parent
2025-10-20 11:57:09 -04:00
sbwalker
5875c1caa7 fix #5671 - copy page and module settings from parent 2025-10-20 11:56:53 -04:00
Ben
ebfcd59c44 Fix #5714: update the default order of profile fields. 2025-10-20 22:09:21 +08:00
Shaun Walker
73dc4c6e5f Merge pull request #5730 from sbwalker/dev
rollback #5728 - existing behavior is correct
2025-10-20 08:03:32 -04:00
sbwalker
0c514743b7 rollback #5728 - existing behavior is correct 2025-10-20 08:03:14 -04:00
Shaun Walker
1e11b0f3a3 Merge pull request #5729 from sbwalker/dev
fix #5705 - improve error handling and efficiency in NotificationJob - credit @beolafsen
2025-10-19 14:03:23 -04:00
sbwalker
e7ae1b26d1 fix #5705 - improve error handling and efficiency in NotificationJob - credit @beolafsen 2025-10-19 14:02:56 -04:00
Shaun Walker
46fa9abf43 Merge pull request #5728 from sbwalker/dev
fix #5714 - order Profile properties by Category and then ViewOrder
2025-10-19 13:43:48 -04:00
sbwalker
d837cd8af5 fix #5714 - order Profile properties by Category and then ViewOrder 2025-10-19 13:43:27 -04:00
Shaun Walker
cca6aff735 Merge pull request #5727 from sbwalker/dev
fix #5708 - resolve issue saving settings
2025-10-19 13:34:39 -04:00
sbwalker
2be11b52c3 fix #5708 - resolve issue saving settings 2025-10-19 13:34:21 -04:00
Shaun Walker
7b026c5b14 Merge pull request #5716 from zyhfish/task/fix-5715
Fix #5715: delete role settings.
2025-10-15 10:52:43 -04:00
Ben
9135894053 Fix #5715: delete settings with api. 2025-10-15 22:48:34 +08:00
Shaun Walker
8ebe34b038 Merge pull request #5723 from sbwalker/dev
add internal theme template to application template
2025-10-15 10:37:22 -04:00
sbwalker
7ef4376363 add internal theme template to application template 2025-10-15 10:37:04 -04:00
Shaun Walker
9a4bfd7009 Merge pull request #5718 from mdmontesinos/fix-5717
fix #5717: add sync events when importing settings
2025-10-15 10:05:36 -04:00
Shaun Walker
356e350588 Merge pull request #5722 from sbwalker/dev
add internal module template to application template
2025-10-15 09:53:45 -04:00
sbwalker
b976983a36 add internal module template to application template 2025-10-15 09:53:28 -04:00
Shaun Walker
7ce7020b51 Merge pull request #5721 from sbwalker/dev
upgrade to .NET 10 RC2
2025-10-15 08:13:47 -04:00
sbwalker
d22949522f upgrade to .NET 10 RC2 2025-10-15 08:13:25 -04:00
David Montesinos
8bac8677c5 fix #5717: add sync events when importing settings
Fixes #5717 by adding a sync event for each added/updated setting in the import process.
2025-10-15 11:04:23 +02:00
Ben
4a4edfa857 Fix #5715: delete role settings. 2025-10-15 16:20:06 +08:00
Shaun Walker
2648887f7d Merge pull request #5713 from sbwalker/dev
update FixProps to .NET 10
2025-10-14 15:51:08 -04:00
sbwalker
eac7ad90e3 update FixProps to .NET 10 2025-10-14 15:50:52 -04:00
Shaun Walker
75c7b55b20 Merge pull request #5712 from sbwalker/dev
update external module/theme templates to .NET 10
2025-10-14 15:35:58 -04:00
sbwalker
23ae819b70 update external module/theme templates to .NET 10 2025-10-14 15:35:42 -04:00
Shaun Walker
f908637313 Merge pull request #5711 from sbwalker/dev
remove custom scroll position script for static rendering as this is fixed in .NET 10
2025-10-14 13:42:10 -04:00
sbwalker
68aeee7c45 remove custom scroll position script for static rendering as this is fixed in .NET 10 2025-10-14 13:41:49 -04:00
Shaun Walker
e4248ed569 Merge pull request #5710 from sbwalker/dev
improve support for internal module/theme templates
2025-10-14 13:37:54 -04:00
sbwalker
7cf325f4f6 improve support for internal module/theme templates 2025-10-14 13:37:39 -04:00
Shaun Walker
a80e449e9c Merge pull request #5709 from sbwalker/dev
use consistent pattern for settings
2025-10-14 13:01:55 -04:00
sbwalker
83b56966f4 use consistent pattern for settings 2025-10-14 13:01:34 -04:00
Shaun Walker
cc2e34fc0b Merge pull request #5707 from sbwalker/dev
fix internal template logic so that assembly name is determined dynamically
2025-10-13 14:43:25 -04:00
sbwalker
bc617db649 fix internal template logic so that assembly name is determined dynamically 2025-10-13 14:42:53 -04:00
Shaun Walker
4a57abc99d Merge pull request #5706 from sbwalker/dev
improve error handling when handling module migrations
2025-10-13 14:20:06 -04:00
sbwalker
db85d1fbc3 improve error handling when handling module migrations 2025-10-13 14:19:49 -04:00
Shaun Walker
20f2eeefbf Merge pull request #5704 from sbwalker/dev
use ModelBase in module template
2025-10-13 11:51:03 -04:00
sbwalker
02c4da5539 use ModelBase in module template 2025-10-13 11:50:46 -04:00
Shaun Walker
8e10a8e042 Remove installation ID, version, and date
Removed installation-related settings from appsettings.json.
2025-10-10 15:31:13 -04:00
Shaun Walker
0c3aed5fa9 Update appsettings.json 2025-10-10 15:29:38 -04:00
sbwalker
95ec163f2c upgrade to .NET 10 RC1 2025-10-10 15:23:04 -04:00
Shaun Walker
bf2d0e35d3 Merge pull request #5700 from sbwalker/dev
use class on element rather than span wrapper
2025-10-09 13:16:33 -04:00
sbwalker
002cf28e12 use class on element rather than span wrapper 2025-10-09 13:16:16 -04:00
Shaun Walker
c0a75ba665 Merge pull request #5699 from leigh-pointer/Bootstrap-5.3.8
Update Framework and Oqtane Theme to Bootstrap 5.3.8
2025-10-09 10:19:49 -04:00
Leigh Pointer
4b05406d40 Update Framework and Oqtane Theme to 5.3.8
Oqtane Framework
https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/js/bootstrap.bundle.min.js
https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/css/bootstrap.min.css

Oqtane Theme
https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.8/cyborg/bootstrap.min.css
2025-10-08 15:00:03 +02:00
Shaun Walker
832f94070f Merge pull request #5697 from sbwalker/dev
allow site templates to support shared modules
2025-10-07 08:09:49 -04:00
sbwalker
cf761f56d4 allow site templates to support shared modules 2025-10-07 08:09:34 -04:00
Shaun Walker
27ba8dfeab Merge pull request #5688 from zyhfish/task/exclude-package-assets
exclude package assets in solution.
2025-10-07 07:43:32 -04:00
Shaun Walker
044bd54201 Merge pull request #5692 from leigh-pointer/glow
fixed cropped glow on the Oqtane Logo
2025-10-07 07:42:28 -04:00
Shaun Walker
e48ba633be Merge pull request #5693 from zyhfish/task/fix-5691
Fix #5691: always display toast message.
2025-10-07 07:41:50 -04:00
Shaun Walker
08757b42df Merge pull request #5695 from zyhfish/task/fix-5694
Fix #5694: update the route.
2025-10-07 07:38:59 -04:00
Leigh Pointer
a59f2e7ca6 Merge remote-tracking branch 'upstream/dev' into dev 2025-10-06 14:39:25 +02:00
Ben
e9a672ebd0 Fix #5694: update the route. 2025-10-06 16:08:02 +08:00
Ben
72e475bca5 Fix #5691: always display toast message. 2025-10-04 09:49:05 +08:00
Leigh Pointer
c49637444a fixed glow on the Oqtane Logo 2025-10-03 18:39:34 +02:00
Leigh Pointer
b1cc0ffc13 Fixed the cropped glow on the Oqtane logo 2025-10-03 18:38:07 +02:00
Leigh Pointer
4e49092434 Merge remote-tracking branch 'upstream/dev' into dev 2025-10-03 18:33:52 +02:00
Ben
7713f18ddf exclude package assets in solution. 2025-10-02 11:06:35 +08:00
Shaun Walker
c1880c54ce Update README.md 2025-10-01 08:27:26 -04:00
Shaun Walker
6a43bcf458 Merge pull request #5685 from oqtane/master
6.2.1 Release
2025-09-29 16:43:35 -04:00
Shaun Walker
ecec06b616 Merge pull request #5684 from oqtane/dev
6.2.1 Release
2025-09-29 16:43:06 -04:00
Shaun Walker
368c9e60ea Update README.md 2025-09-29 16:41:58 -04:00
Shaun Walker
f5b4e52526 Merge pull request #5683 from sbwalker/dev
update azuredeploy.json
2025-09-29 16:39:53 -04:00
sbwalker
a939a286ae update azuredeploy.json 2025-09-29 16:39:36 -04:00
Shaun Walker
88acb2a665 Merge pull request #5682 from sbwalker/dev
remove logo-white.png from application template as it causes conflict
2025-09-29 15:12:35 -04:00
sbwalker
e7c2ad5965 remove logo-white.png from application template as it causes conflict 2025-09-29 15:11:33 -04:00
Shaun Walker
071cceb7f8 Merge pull request #5681 from sbwalker/dev
exclude module/theme template files from Oqtane.Server Nuget package
2025-09-29 14:53:27 -04:00
sbwalker
377465e361 exclude module/theme template files from Oqtane.Server Nuget package 2025-09-29 14:53:13 -04:00
Shaun Walker
0f738113af Merge pull request #5679 from sbwalker/dev
add back IsPackable to Oqtane.Server to ensure static web assets are included
2025-09-29 14:04:21 -04:00
sbwalker
534a6147a8 add back IsPackable to Oqtane.Server to ensure static web assets are included 2025-09-29 14:04:00 -04:00
Shaun Walker
87313c8082 Merge pull request #5678 from sbwalker/dev
update Swashbuckle, Mailkit to latest versions
2025-09-29 13:18:11 -04:00
sbwalker
b315f09640 update Swashbuckle, Mailkit to latest versions 2025-09-29 13:17:56 -04:00
Shaun Walker
3025f11ea8 Merge pull request #5677 from sbwalker/dev
update Radzen.Blazor to latest version
2025-09-29 13:14:11 -04:00
sbwalker
8fb391717f update Radzen.Blazor to latest version 2025-09-29 13:13:57 -04:00
Shaun Walker
583ccf9811 Merge pull request #5676 from sbwalker/dev
synchronize static assets with .NET MAUI
2025-09-29 11:32:50 -04:00
sbwalker
cd6ec49cc8 synchronize static assets with .NET MAUI 2025-09-29 11:32:29 -04:00
Shaun Walker
2b9c5b1728 Merge pull request #5675 from sbwalker/dev
add directory.build.props to centralize propertygroup settings
2025-09-29 09:56:48 -04:00
sbwalker
0e772974a6 add directory.build.props to centralize propertygroup settings 2025-09-29 09:56:35 -04:00
Shaun Walker
62e181cfc3 Merge pull request #5674 from sbwalker/dev
implement single logout for OIDC
2025-09-29 09:39:29 -04:00
sbwalker
68233951cb implement single logout for OIDC 2025-09-29 09:39:15 -04:00
Shaun Walker
d8531899b6 Merge pull request #5672 from sbwalker/dev
change term from existing to current
2025-09-29 07:41:02 -04:00
sbwalker
bc2e7915cc change term from existing to current 2025-09-29 07:40:42 -04:00
Shaun Walker
b18d47afa3 Merge pull request #5670 from zyhfish/task/insert-file-link
do not replace the selected text when insert file link.
2025-09-29 07:26:58 -04:00
Ben
297f91da00 do not replace the selected text when insert file link. 2025-09-28 18:05:17 +08:00
Ben
2bdc7e1bc3 do not replace the selected text when insert file link. 2025-09-28 14:51:55 +08:00
Shaun Walker
dc0a5c8bb0 Merge pull request #5668 from zyhfish/task/radzen-editor-insert-link
enable to insert file link in radzen editor.
2025-09-27 07:30:41 -04:00
Ben
2a302a187a enable to insert file link in radzen editor. 2025-09-27 09:31:16 +08:00
Shaun Walker
407a3a19b6 Clarify Installation Wizard instructions in README
Updated wording for clarity regarding the Installation Wizard.
2025-09-26 08:57:29 -04:00
Shaun Walker
d462fc7afd Update README.md 2025-09-26 08:54:43 -04:00
Shaun Walker
0b425e3bd9 Merge pull request #5667 from sbwalker/dev
include logo as it is a dependency of the default site template
2025-09-26 08:30:25 -04:00
sbwalker
3efc12fabc include logo as it is a dependency of the default site template 2025-09-26 08:30:05 -04:00
Shaun Walker
852385a192 Merge pull request #5665 from leigh-pointer/ThemeManagement
Update to Themes Editresx
2025-09-26 07:57:51 -04:00
Shaun Walker
8077025fe8 Merge pull request #5666 from sbwalker/dev
consolidate template packaging into release.cmd
2025-09-26 07:57:29 -04:00
sbwalker
6f0da0c002 consolidate template packaging into release.cmd 2025-09-26 07:57:13 -04:00
Leigh Pointer
5dbea610c1 Update to Themes Editresx
Small typo fix
2025-09-26 12:41:56 +02:00
Leigh Pointer
026d716ece Merge remote-tracking branch 'upstream/dev' into dev 2025-09-26 12:33:37 +02:00
Shaun Walker
92496f4369 Merge pull request #5664 from sbwalker/dev
update README
2025-09-25 14:47:05 -04:00
sbwalker
ec00b1162f update README 2025-09-25 14:46:51 -04:00
Shaun Walker
e638aee1ac Merge pull request #5663 from sbwalker/dev
changes to template.json based on https://github.com/sayedihashimi/template-sample
2025-09-25 14:43:02 -04:00
sbwalker
5420f625b4 changes to template.json based on https://github.com/sayedihashimi/template-sample 2025-09-25 14:42:40 -04:00
Shaun Walker
77fa7f4a79 Merge pull request #5662 from sbwalker/dev
add all direct package dependencies to Application Template
2025-09-25 14:09:57 -04:00
sbwalker
2db1fe0890 add all direct package dependencies to Application Template 2025-09-25 14:09:41 -04:00
Shaun Walker
63bb70785a Merge pull request #5661 from sbwalker/dev
allow themes to define usage permissions similar to modules
2025-09-25 13:55:17 -04:00
sbwalker
8d23d9aba3 allow themes to define usage permissions similar to modules 2025-09-25 13:55:02 -04:00
Shaun Walker
bebe70f46b Merge pull request #5655 from Raceeend/template_package_reference
Update Oqtane.Application.Server.csproj
2025-09-24 08:18:07 -04:00
Shaun Walker
34f2db5985 Merge pull request #5654 from mdmontesinos/fix-5648
Fix #5648: Restore order of SetImage in FileManager
2025-09-24 08:17:51 -04:00
Shaun Walker
8e75c09e3f Merge pull request #5653 from tvatavuk/patch-3
RadzenTextEditor.placeholder.cs in RadzenTextEditor for docs
2025-09-24 08:17:37 -04:00
Shaun Walker
b5d4eaa36e Merge pull request #5652 from tvatavuk/patch-2
Fix XML comment in UnzipFileAsync method
2025-09-24 08:17:24 -04:00
Pieter Kuyck
116d163b9d Update Oqtane.Application.Server.csproj
Add Package reference that will create the BlazorDebugProxy folder.
2025-09-23 22:54:34 +02:00
David Montesinos
2cb568773c Restore order of SetImage in FileManager
Fixes #5648
2025-09-23 16:21:20 +02:00
Tonći Vatavuk
916019f015 RadzenTextEditor.placeholder.cs in RadzenTextEditor for docs
This is just a placeholder file
It is necessary for the documentation to successfully build this project.
Reason is that docfx will run the .net compiler and find references
to this class in the project.
But since the real class is just a .razor file, ATM docfx will fail.
2025-09-23 16:18:52 +02:00
Tonći Vatavuk
e83d7e9d57 Fix XML comment in UnzipFileAsync method
Removed an unnecessary XML comment parameter closing tag.
2025-09-23 15:21:03 +02:00
Shaun Walker
151af30259 Merge pull request #5647 from sbwalker/dev
improve Profile ability to use Settings
2025-09-21 11:12:27 -04:00
sbwalker
7fed6bb93a improve Profile ability to use Settings 2025-09-21 11:12:07 -04:00
Shaun Walker
382a8eb8f3 Merge pull request #5644 from leigh-pointer/PkgUpdates
Package Updates
2025-09-21 08:39:26 -04:00
Leigh Pointer
9508ff68db nuspec files updated 2025-09-21 14:29:05 +02:00
Shaun Walker
9684e6e1a8 Merge pull request #5645 from sbwalker/dev
use MailboxAddress approach sugested by @jstedfast
2025-09-21 08:09:37 -04:00
sbwalker
52745b1946 use MailboxAddress approach sugested by @jstedfast 2025-09-21 08:09:11 -04:00
Leigh Pointer
3db2d03a37 Package Updates
Updated Client Radzen.Blazo to 7.3.5
Updated Server HtmlAgilityPack 1.12.3
2025-09-20 11:49:10 +02:00
Leigh Pointer
a85ae69ed1 Merge remote-tracking branch 'upstream/dev' into dev 2025-09-20 10:49:28 +02:00
Shaun Walker
9052d6abb6 Merge pull request #5643 from sbwalker/dev
add whitespace
2025-09-19 15:29:56 -04:00
sbwalker
3c528f0b93 add whitespace 2025-09-19 15:29:30 -04:00
Shaun Walker
3322297eaa Merge pull request #5642 from sbwalker/dev
improve migration history
2025-09-19 15:25:25 -04:00
sbwalker
3c1167d359 improve migration history 2025-09-19 15:25:11 -04:00
Shaun Walker
9e35a520cc Merge pull request #5641 from sbwalker/dev
add ability to view Migration History
2025-09-19 15:00:14 -04:00
sbwalker
beb4919d97 add ability to view Migration History 2025-09-19 14:59:58 -04:00
Shaun Walker
6895d16a20 Merge pull request #5640 from sbwalker/dev
improve NotificationJob validation logic
2025-09-19 12:46:09 -04:00
sbwalker
05b37080c1 improve NotificationJob validation logic 2025-09-19 12:45:55 -04:00
Shaun Walker
51894de708 Merge pull request #5638 from sbwalker/dev
optimizations to NotificationJob
2025-09-19 09:06:04 -04:00
sbwalker
442ec291a1 optimizations to NotificationJob 2025-09-19 09:05:35 -04:00
Shaun Walker
6ef106be31 Merge pull request #5637 from sbwalker/dev
synchronize Application Template project settings with Oqtane Framework
2025-09-19 08:55:54 -04:00
sbwalker
70551f9d27 synchronize Application Template project settings with Oqtane Framework 2025-09-19 08:55:36 -04:00
Shaun Walker
fe422ed5aa Merge pull request #5636 from sbwalker/dev
fix issues with NotificationJob related to MailKit behavior
2025-09-18 17:24:05 -04:00
sbwalker
1995a96a98 fix issues with NotificationJob related to MailKit behavior 2025-09-18 17:19:30 -04:00
Shaun Walker
4abcc6e58f Merge pull request #5635 from sbwalker/dev
changes to release.cmd
2025-09-18 13:46:33 -04:00
sbwalker
a6f4921055 changes to release.cmd 2025-09-18 13:46:18 -04:00
Leigh Pointer
33f525dbda Merge remote-tracking branch 'upstream/dev' into dev 2025-09-18 15:07:20 +02:00
Shaun Walker
23e83a5e30 Merge pull request #5633 from leigh-pointer/patch-1
Update README.md
2025-09-18 08:48:01 -04:00
Shaun Walker
6abd2cf7fc Merge pull request #5634 from sbwalker/dev
use static form for close button in ModuleMessage to support all render modes
2025-09-18 07:55:48 -04:00
sbwalker
085f137942 use static form for close button in ModuleMessage to support all render modes 2025-09-18 07:55:26 -04:00
Leigh Pointer
62d99d33bd Update README.md
Updated the SDK version number and the url to the microsoft default.
2025-09-18 13:23:07 +02:00
Shaun Walker
57375eaab9 Merge pull request #5632 from sbwalker/dev
update release.cmd
2025-09-17 17:27:06 -04:00
sbwalker
30b7e71cd8 update release.cmd 2025-09-17 17:26:50 -04:00
Shaun Walker
e26bb66405 Merge pull request #5629 from sbwalker/dev
add class selectors for control panel elements
2025-09-17 10:14:32 -04:00
sbwalker
6263bd3a60 add class selectors for control panel elements 2025-09-17 10:14:13 -04:00
Shaun Walker
8bee8d2f3f Revise README instructions for application setup 2025-09-16 14:45:33 -04:00
Shaun Walker
4ffe8fac3a Enhance README with run and debug instructions 2025-09-16 14:44:45 -04:00
Shaun Walker
09a7457c01 Update README.md 2025-09-16 14:41:36 -04:00
Shaun Walker
15a8f0a4ac Merge pull request #5627 from sbwalker/dev
use newer Resource overload methods
2025-09-16 12:50:19 -04:00
sbwalker
503134d38c use newer Resource overload methods 2025-09-16 12:50:01 -04:00
Shaun Walker
e19b8ffed9 Merge pull request #5626 from sbwalker/dev
fix #5616 - show all available modules/themes and indicate if they are installed
2025-09-16 11:36:50 -04:00
sbwalker
c38dc69d3b fix #5616 - show all available modules/themes and indicate if they are installed 2025-09-16 11:36:28 -04:00
Shaun Walker
ff16fd8b9c Merge pull request #5625 from sbwalker/dev
use enum for MessageStyle
2025-09-16 11:16:41 -04:00
sbwalker
880a6e43d1 use enum for MessageStyle 2025-09-16 11:16:23 -04:00
Shaun Walker
188d3b42d8 Merge pull request #5623 from zyhfish/task/fix-5612
Fix #5612: add paging function.
2025-09-16 10:24:30 -04:00
Shaun Walker
c526e01534 Merge pull request #5624 from sbwalker/dev
fix incorrect resourceType in Settings.razor in Application template
2025-09-16 10:23:41 -04:00
sbwalker
dae906d52f fix incorrect resourceType in Settings.razor in Application template 2025-09-16 10:23:26 -04:00
Ben
e620bba0da Fix #5612: add paging function. 2025-09-16 18:21:47 +08:00
Shaun Walker
fae22595aa Merge pull request #5622 from sbwalker/dev
add toast support to ModuleMessage
2025-09-15 16:42:54 -04:00
sbwalker
a528e5eab2 add toast support to ModuleMessage 2025-09-15 16:42:37 -04:00
Shaun Walker
0991925090 Merge pull request #5621 from sbwalker/dev
remove static assets from Application Template
2025-09-15 10:02:47 -04:00
sbwalker
f9741a82bd remove static assets from Application Template 2025-09-15 10:02:29 -04:00
Shaun Walker
f0067d86a6 Merge pull request #5620 from sbwalker/dev
Fix #5613 - add Theme.css for the external theme template
2025-09-15 08:22:10 -04:00
sbwalker
d7aa999f25 add Theme.css for the external theme template 2025-09-15 08:21:28 -04:00
Shaun Walker
ea87497e6d Merge pull request #5618 from zyhfish/task/move-radzen-editor-settings-dialog
Move radzen editor settings dialog  to correct folder.
2025-09-15 08:02:29 -04:00
Shaun Walker
2dc8cabc80 Merge pull request #5619 from sbwalker/dev
improve performance of UpdateSettingsAsync method
2025-09-15 08:00:04 -04:00
sbwalker
4e53dcd8d5 improve performance of UpdateSettingsAsync method 2025-09-15 07:59:46 -04:00
Ben
dd447e802e Move radzen editor settings dialog to correct folder. 2025-09-15 17:05:51 +08:00
Shaun Walker
c7a86aa49c Merge pull request #5611 from sbwalker/dev
remove content files from Oqtane.Server Nuget package
2025-09-12 15:41:34 -04:00
sbwalker
c6e7638e8b remove content files from Oqtane.Server Nuget package 2025-09-12 15:41:18 -04:00
Shaun Walker
166969bc35 Merge pull request #5610 from sbwalker/dev
adding static assets back to Application Template
2025-09-12 15:38:05 -04:00
sbwalker
61d231801a adding static assets back to Application Template 2025-09-12 15:37:47 -04:00
Shaun Walker
cc51f5bb0f Merge pull request #5608 from sbwalker/dev
bump version to 6.2.1
2025-09-12 12:32:06 -04:00
sbwalker
dcd99695e7 bump version to 6.2.1 2025-09-12 12:31:47 -04:00
Shaun Walker
1c78683f4c Merge pull request #5607 from sbwalker/dev
update to .NET SDK 9.0.9
2025-09-12 12:02:16 -04:00
sbwalker
f2124c5ae0 update to .NET SDK 9.0.9 2025-09-12 12:01:57 -04:00
Shaun Walker
868aca9fdb Merge pull request #5606 from sbwalker/dev
remove static assets from Application Template
2025-09-12 11:43:42 -04:00
sbwalker
d12f7b79d2 remove static assets from Application Template 2025-09-12 11:43:25 -04:00
Shaun Walker
600bbdfd0d Merge pull request #5605 from sbwalker/dev
Include content files in Oqtane.Server Nuget package
2025-09-12 11:39:23 -04:00
sbwalker
04bc68de55 Include content files in Oqtane.Server Nuget package 2025-09-12 11:39:03 -04:00
Shaun Walker
82b4f7b611 Merge pull request #5603 from sbwalker/dev
remove OQTANE3 constant
2025-09-12 07:32:12 -04:00
sbwalker
4adba1ab5f remove OQTANE3 constant 2025-09-12 07:31:53 -04:00
Shaun Walker
6d2ac670af Merge pull request #5602 from sbwalker/dev
prevent the creation of fingerprinted static web assets as Oqtane does not support them
2025-09-11 10:19:13 -04:00
sbwalker
64a03b6e91 prevent the creation of fingerprinted static web assets as Oqtane does not support them 2025-09-11 10:18:45 -04:00
Shaun Walker
c88958ae7e Merge pull request #5601 from sbwalker/dev
move and rename FileManagerDialog so that it is clear that it is a dependency of RadzenTextEditor
2025-09-11 08:24:40 -04:00
sbwalker
4278b9992b move and rename FileManagerDialog so that it is clear that it is a dependency of RadzenTextEditor 2025-09-11 08:24:14 -04:00
Shaun Walker
ebac6d51b0 Merge pull request #5598 from sbwalker/dev
improve sort order of user profile options using settings
2025-09-10 17:18:07 -04:00
sbwalker
fba4f23f71 improve sort order of user profile options using settings 2025-09-10 17:17:47 -04:00
Shaun Walker
7231d2f49e Merge pull request #5597 from sbwalker/dev
add upgrade logic to cleanup assets which were moved to a new location in 6.2.0
2025-09-10 17:02:26 -04:00
sbwalker
d871bffdd5 add upgrade logic to cleanup assets which were moved to a new location in 6.2.0 2025-09-10 17:01:59 -04:00
Shaun Walker
5630b4842c Merge pull request #5595 from sbwalker/dev
upate README for Application Template
2025-09-10 07:55:52 -04:00
sbwalker
b19141b361 upate README for Application Template 2025-09-10 07:55:31 -04:00
Shaun Walker
732e279605 Merge pull request #5594 from sbwalker/dev
fix issue with Application template
2025-09-09 16:47:57 -04:00
sbwalker
fa173d492c fix issue with Application template 2025-09-09 16:47:43 -04:00
Shaun Walker
3259494d45 Merge pull request #5593 from oqtane/master
6.2.0 Release
2025-09-09 16:24:37 -04:00
Shaun Walker
0a03eb620a Merge pull request #5592 from oqtane/dev
6.2.0 Release
2025-09-09 16:24:12 -04:00
Shaun Walker
701d8c9a57 Update README.md 2025-09-09 16:23:07 -04:00
Shaun Walker
fdca8a2890 Merge pull request #5591 from sbwalker/dev
ensure Radzen.Blazor static assets are included in publish output
2025-09-09 14:25:08 -04:00
sbwalker
22e2a4da1e ensure Radzen.Blazor static assets are included in publish output 2025-09-09 14:24:53 -04:00
Shaun Walker
409523912b Merge pull request #5590 from sbwalker/dev
use standard port #'s
2025-09-09 13:31:08 -04:00
sbwalker
d5c68444c3 use standard port #'s 2025-09-09 13:30:53 -04:00
Shaun Walker
ffa93e0ee7 Merge pull request #5589 from sbwalker/dev
profile improvements
2025-09-09 08:52:36 -04:00
sbwalker
3f4f1a8278 profile improvements 2025-09-09 08:52:20 -04:00
Shaun Walker
8e70949880 Merge pull request #5588 from sbwalker/dev
improve setting import
2025-09-08 12:55:58 -04:00
sbwalker
be8436d237 improve setting import 2025-09-08 12:55:45 -04:00
Shaun Walker
876f13be5e Merge pull request #5587 from sbwalker/dev
add setting import
2025-09-08 12:13:34 -04:00
sbwalker
dfca6640da add setting import 2025-09-08 12:13:17 -04:00
Shaun Walker
a2e57bc54c Merge pull request #5585 from sbwalker/dev
improve validation
2025-09-05 17:38:17 -04:00
sbwalker
dcc2e59e46 improve validation 2025-09-05 17:38:02 -04:00
Shaun Walker
90e721b172 Merge pull request #5584 from sbwalker/dev
added a Setting Management UI
2025-09-05 17:20:50 -04:00
sbwalker
94391875d5 added a Setting Management UI 2025-09-05 17:20:31 -04:00
Shaun Walker
43d06c042d Merge pull request #5583 from sbwalker/dev
allow installer logo to be overridden
2025-09-05 13:12:56 -04:00
sbwalker
3e12910fbd allow installer logo to be overridden 2025-09-05 13:12:39 -04:00
Shaun Walker
ba70ebe23c Merge pull request #5582 from sbwalker/dev
update application template
2025-09-05 12:36:18 -04:00
sbwalker
b739841495 update application template 2025-09-05 12:36:03 -04:00
Shaun Walker
acabc75aa6 Merge pull request #5581 from sbwalker/dev
restructure text editors and static assets
2025-09-05 12:33:00 -04:00
sbwalker
27041f464f restructure text editors and static assets 2025-09-05 12:32:43 -04:00
Shaun Walker
9f923ae968 Merge pull request #5577 from zyhfish/task/radzen-text-editor
implement radzen text editor.
2025-09-05 11:13:52 -04:00
Shaun Walker
9c7d832357 Merge pull request #5580 from sbwalker/dev
exception handling needs to encapsulate entire method
2025-09-05 11:13:37 -04:00
sbwalker
e913c10d5b exception handling needs to encapsulate entire method 2025-09-05 11:13:21 -04:00
Shaun Walker
c698188901 Merge pull request #5576 from W6HBR/dev
fix job status issue for disabled jobs
2025-09-05 11:07:52 -04:00
Shaun Walker
8fd67621ac Merge pull request #5579 from sbwalker/dev
update dependencies in Oqtane.Server.nusepc
2025-09-05 11:05:47 -04:00
sbwalker
0c60085e09 update dependencies in Oqtane.Server.nusepc 2025-09-05 11:05:18 -04:00
Shaun Walker
1826316c80 Merge pull request #5567 from thabaum/Update-v6.2.0-azure-deploy-and-dependencies
Update v6.2.0 azure deploy and Oqtane.Server project dependencies
2025-09-05 11:02:45 -04:00
Shaun Walker
07341aeebe Fix Azure deployment link in README
Updated Azure deployment link to use the master branch.
2025-09-05 11:02:00 -04:00
Shaun Walker
9f6945dda2 Merge pull request #5578 from oqtane/master
Update azuredeploy.json
2025-09-05 11:01:15 -04:00
Shaun Walker
b39b568b4c Update azuredeploy.json 2025-09-05 11:00:06 -04:00
Ben
e59d5fd339 implement radzen text editor. 2025-09-05 20:36:50 +08:00
Jon Welfringer
b7bc527d6c Added resource message for Message.Job.Disabled 2025-09-04 21:52:24 -07:00
Jon Welfringer
1ea76d06d1 Change StartJob to check if job is enabled 2025-09-04 21:47:51 -07:00
Jon Welfringer
b049be9d83 Change IsStarted to follow IsEnabled value upon startup.
Changes behavior of IsStarted to follow the same value of IsEnabled.
2025-09-04 21:44:14 -07:00
Shaun Walker
966fc55594 Merge pull request #5574 from sbwalker/dev
fix #5570 - multi-database installation authentication issue
2025-09-04 14:02:24 -04:00
sbwalker
ca9ddbd90f fix #5570 - multi-database installation authentication issue 2025-09-04 14:01:42 -04:00
Shaun Walker
0d04926d9f Merge pull request #5569 from sbwalker/dev
fix issue in application template
2025-09-02 17:11:32 -04:00
sbwalker
2b500d41ca fix issue in application template 2025-09-02 17:11:23 -04:00
Shaun Walker
5c67eeea58 Merge pull request #5568 from sbwalker/dev
fix issue in default module template
2025-09-02 17:10:06 -04:00
sbwalker
09daf3f6cc fix issue in default module template 2025-09-02 17:09:55 -04:00
Cody
9a06a3311e Update azuredeploy.json to v6.2.0 2025-09-02 12:58:04 -07:00
Cody
304694fbf9 Update to latest SQLitePCLRaw.bundle_e_sqlite3 & Swashbuckle.AspNetCore Package Dependencies 2025-09-02 12:53:42 -07:00
Shaun Walker
96ba42df96 Merge pull request #5565 from sbwalker/dev
bump version to 6.2.0
2025-09-02 13:59:38 -04:00
sbwalker
e7bc11d026 bump version to 6.2.0 2025-09-02 13:59:27 -04:00
Shaun Walker
1272305355 Merge pull request #5564 from sbwalker/dev
fix help text related to module/theme upload
2025-09-02 08:50:45 -04:00
sbwalker
30c6da13c2 fix help text related to module/theme upload 2025-09-02 08:49:32 -04:00
Shaun Walker
5aacb2b877 Merge pull request #5563 from sbwalker/dev
allow modules to be able to specify the databases they support
2025-09-02 08:33:51 -04:00
sbwalker
b5fdf42c37 allow modules to be able to specify the databases they support 2025-09-02 08:32:46 -04:00
Leigh Pointer
4ba7e034b7 Merge remote-tracking branch 'upstream/dev' into dev 2025-08-31 12:56:43 +02:00
Shaun Walker
c81d677c5c Merge pull request #5559 from sbwalker/dev
added support for cookie domain option in User Management Settings
2025-08-30 08:01:56 -04:00
sbwalker
6daf675e52 added support for cookie domain option in User Management Settings 2025-08-30 08:01:18 -04:00
Shaun Walker
3f7a7f3340 Merge pull request #5558 from sbwalker/dev
added StaticAssetPath properties to base classes
2025-08-30 07:49:06 -04:00
sbwalker
1ebf3c4077 added StaticAssetPath properties to base classes 2025-08-30 07:48:26 -04:00
Shaun Walker
1f1173ae03 Merge pull request #5557 from sbwalker/dev
add comments
2025-08-30 07:27:23 -04:00
sbwalker
efa466e1d6 add comments 2025-08-30 07:26:37 -04:00
Shaun Walker
cefe349b4e Merge pull request #5555 from sbwalker/dev
remove hardcoded references to LocalDB
2025-08-29 17:17:27 -04:00
sbwalker
a9bc356f37 remove hardcoded references to LocalDB 2025-08-29 17:16:42 -04:00
Shaun Walker
6fc791020c Merge pull request #5554 from sbwalker/dev
move default template static assets
2025-08-29 16:34:35 -04:00
sbwalker
713ec1b373 move default template static assets 2025-08-29 16:33:51 -04:00
Shaun Walker
e3fa781122 Merge pull request #5553 from sbwalker/dev
improve default theme template to follow RCL/Nuget standards
2025-08-29 16:31:18 -04:00
sbwalker
e4b6d0ff29 improve default theme template to follow RCL/Nuget standards 2025-08-29 16:30:49 -04:00
Shaun Walker
cd2a328560 Merge pull request #5552 from sbwalker/dev
improve default module template to follow RCL/Nuget standards
2025-08-29 16:21:06 -04:00
sbwalker
d2d88d4b5e improve default module template to follow RCL/Nuget standards 2025-08-29 16:20:16 -04:00
Shaun Walker
0067cc4266 Added FixProps command line utility 2025-08-29 15:19:07 -04:00
Shaun Walker
da3afefa8d Merge pull request #5551 from sbwalker/dev
update default module/theme templates to use projectType rather than dependency in nuspec file
2025-08-29 15:15:12 -04:00
sbwalker
ab534d07f3 update default module/theme templates to use projectType rather than dependency in nuspec file 2025-08-29 15:14:48 -04:00
Shaun Walker
49c513ac9b Merge pull request #5550 from sbwalker/dev
add support for packageType in nuspec files for minimum Oqtane version
2025-08-29 14:31:07 -04:00
sbwalker
6f7a18674e add support for packageType in nuspec files for minimum Oqtane version 2025-08-29 14:30:49 -04:00
Shaun Walker
0f559ba42d Merge pull request #5546 from sbwalker/dev
install wizard should use RenderMode and Runtime values from appsettings.json when creating site
2025-08-27 14:28:43 -04:00
sbwalker
2af02fae95 install wizard should use RenderMode and Runtime values from appsettings.json when creating site 2025-08-27 14:28:23 -04:00
Shaun Walker
006423e32e Change RenderMode from Interactive to Static 2025-08-27 14:27:28 -04:00
Shaun Walker
23f29ca55d Change RenderMode from Interactive to Static 2025-08-27 14:27:01 -04:00
Shaun Walker
68a7571741 Change RenderMode from Interactive to Static 2025-08-27 14:26:47 -04:00
Shaun Walker
10e60e352a Merge pull request #5545 from sbwalker/dev
improve help text
2025-08-27 14:08:08 -04:00
sbwalker
3b16ae8cc0 improve help text 2025-08-27 14:07:51 -04:00
Shaun Walker
66c4737021 Merge pull request #5533 from zyhfish/task/fix-5532
Fix #5532: add require nonce setting.
2025-08-27 13:55:20 -04:00
Shaun Walker
8684e03af1 Merge pull request #5544 from sbwalker/dev
fix #5531 - external login single sign-on for multiple sites
2025-08-27 13:54:46 -04:00
sbwalker
edad9e6b3c fix #5531 - external login single sign-on for multiple sites 2025-08-27 13:54:30 -04:00
Shaun Walker
66b89752d3 Merge pull request #5543 from sbwalker/dev
fix resources in default theme template
2025-08-27 12:29:04 -04:00
sbwalker
9a6195edf1 fix resources in default theme template 2025-08-27 12:28:51 -04:00
Shaun Walker
2bd07b54b6 Merge pull request #5542 from sbwalker/dev
optimize client startup in templates
2025-08-27 12:21:16 -04:00
sbwalker
7cf9d9ad65 optimize client startup in templates 2025-08-27 12:20:59 -04:00
Shaun Walker
4dff30ec8c Merge pull request #5540 from sbwalker/dev
default index component to interactive
2025-08-27 09:21:34 -04:00
sbwalker
581f14e661 default index component to interactive 2025-08-27 09:21:19 -04:00
Shaun Walker
8ccdc37b64 Merge pull request #5538 from sbwalker/dev
fix naming
2025-08-26 17:22:23 -04:00
sbwalker
9e85b35498 fix naming 2025-08-26 17:22:10 -04:00
Shaun Walker
fff408a5bf Merge pull request #5537 from sbwalker/dev
application template changes
2025-08-26 17:16:01 -04:00
sbwalker
4d5168c998 application template changes 2025-08-26 17:15:46 -04:00
Shaun Walker
bf2c978f1d Merge pull request #5536 from sbwalker/dev
optimize startup
2025-08-26 15:27:51 -04:00
sbwalker
ec06c1cdf1 optimize startup 2025-08-26 15:27:35 -04:00
Ben
f451cfce09 Fix #5532: remove duplicated semi colon. 2025-08-26 20:27:41 +08:00
Ben
91e55aeb9b Fix #5532: change the default value to true. 2025-08-26 20:26:11 +08:00
Ben
919fb5012f Fix #5532: add require nonce setting. 2025-08-26 18:13:09 +08:00
Leigh Pointer
74a5fb656e Merge remote-tracking branch 'upstream/dev' into dev 2025-08-22 22:31:19 +02:00
Shaun Walker
2bb6226e78 Merge pull request #5530 from sbwalker/dev
remove unecessary content exclusion
2025-08-22 14:25:59 -04:00
sbwalker
6a0c47f7b1 remove unecessary content exclusion 2025-08-22 14:21:49 -04:00
Shaun Walker
31b688cbf6 Merge pull request #5529 from sbwalker/dev
make kestrel the default web server for the app template
2025-08-22 10:06:25 -04:00
sbwalker
7f1fed2fb1 make kestrel the default web server for the app template 2025-08-22 10:06:10 -04:00
Shaun Walker
aa6c876b12 Merge pull request #5528 from sbwalker/dev
more template optimizations
2025-08-22 09:17:40 -04:00
sbwalker
4e33aeef89 more template optimizations 2025-08-22 09:17:24 -04:00
Shaun Walker
e2601dcf05 Merge pull request #5527 from sbwalker/dev
increment template version
2025-08-22 08:55:37 -04:00
sbwalker
247baa375d increment template version 2025-08-22 08:55:20 -04:00
Shaun Walker
a4adba846e Merge pull request #5526 from sbwalker/dev
declare dependencies in nuspec files and optimize application template
2025-08-22 08:42:09 -04:00
sbwalker
52799c7cb0 declare dependencies in nuspec files and optimize application template 2025-08-22 08:41:52 -04:00
Shaun Walker
a8635dc555 Merge pull request #5523 from sbwalker/dev
fix #5520 - site soft delete should only be visible to Host users
2025-08-21 09:59:31 -04:00
sbwalker
cca0f2219e fix #5520 - site soft delete should only be visible to Host users 2025-08-21 09:59:15 -04:00
Shaun Walker
d2f8c3c2bb Merge pull request #5522 from sbwalker/dev
fix #5519 - Site hard delete exception
2025-08-21 09:57:44 -04:00
sbwalker
0f38df053f fix #5519 - Site hard delete exception 2025-08-21 09:57:29 -04:00
Shaun Walker
5c926a10a7 Merge pull request #5521 from sbwalker/dev
template updates
2025-08-21 09:56:18 -04:00
sbwalker
036bbb418e template updates 2025-08-21 09:56:03 -04:00
Leigh Pointer
bc5ce74925 Merge remote-tracking branch 'upstream/dev' into dev 2025-08-20 18:30:09 +02:00
Shaun Walker
93d224fa37 Merge pull request #5518 from sbwalker/dev
support for staticwebassets folder in Nuget packages
2025-08-20 07:09:50 -04:00
sbwalker
5b45e3e417 support for staticwebassets folder in Nuget packages 2025-08-20 07:09:33 -04:00
Leigh Pointer
338c652635 Merge remote-tracking branch 'upstream/dev' into dev 2025-08-20 12:53:04 +02:00
Shaun Walker
c2f2dfd837 Merge pull request #5517 from sbwalker/dev
fix filename in template
2025-08-19 14:01:38 -04:00
sbwalker
2f2baf12fb fix filename in template 2025-08-19 14:01:25 -04:00
Shaun Walker
052c339d0d Merge pull request #5516 from sbwalker/dev
add additional SSL connection options for SMTP
2025-08-19 13:16:51 -04:00
sbwalker
96192e2e06 add additional SSL connection options for SMTP 2025-08-19 13:16:37 -04:00
Shaun Walker
ea9fa30358 Merge pull request #5515 from sbwalker/dev
template improvements
2025-08-19 12:27:10 -04:00
sbwalker
78f8e2f484 template improvements 2025-08-19 12:26:54 -04:00
Shaun Walker
0fe2a3fb80 Merge pull request #5514 from sbwalker/dev
add project reference in AppHost to Server so that dependencies will be automatically copied
2025-08-19 12:10:35 -04:00
sbwalker
a340f52973 add project reference in AppHost to Server so that dependencies will be automatically copied 2025-08-19 12:10:15 -04:00
Shaun Walker
bd94b715ba Merge pull request #5513 from sbwalker/dev
Resources for Interactive module components should be managed via JS Interop
2025-08-19 12:05:58 -04:00
sbwalker
b9a97ffa4c Resources for Interactive module components should be managed via JS Interop 2025-08-19 12:05:39 -04:00
Shaun Walker
5a37ab1b89 Merge pull request #5510 from sbwalker/dev
modify template content
2025-08-17 10:54:01 -04:00
Shaun Walker
67a6ac2240 Merge branch 'dev' into dev 2025-08-17 10:53:54 -04:00
sbwalker
7b42845ecc modify template content 2025-08-17 10:53:22 -04:00
Shaun Walker
3ef39896d1 Merge pull request #5509 from sbwalker/dev
update Azure ARM template to 6.1.5
2025-08-17 10:29:37 -04:00
sbwalker
b01f3b505d update Azure ARM template to 6.1.5 2025-08-17 10:29:25 -04:00
Shaun Walker
84c5e4c30b Update README.md 2025-08-17 10:10:56 -04:00
Shaun Walker
abc0f3943e Merge pull request #5507 from oqtane/master
6.1.5 Release
2025-08-17 09:59:14 -04:00
Shaun Walker
c7b71db015 Merge pull request #5506 from oqtane/dev
6.1.5 Release
2025-08-17 09:58:54 -04:00
Shaun Walker
f5a8a953bb Update README.md 2025-08-16 09:39:09 -04:00
Shaun Walker
8e965912aa Update README.md 2025-08-16 09:34:21 -04:00
Shaun Walker
6c3cfb0c7a Update README.md 2025-08-16 09:33:28 -04:00
Shaun Walker
85d162aa9d Update README.md 2025-08-16 09:32:50 -04:00
Shaun Walker
67c460dfa5 Merge pull request #5502 from thabaum/6.1.5-Maui-Version-9.0.100
Fixes #5501: Updates Maui Project Dependencies to version 9.0.100
2025-08-15 16:15:49 -04:00
Cody
83d35dbc65 Updates Maui Project Dependencies to version 9.0.100 2025-08-15 11:19:00 -07:00
Shaun Walker
86735a5afd Update README.md 2025-08-15 14:15:13 -04:00
Shaun Walker
6ecbb89469 Merge pull request #5500 from sbwalker/dev
consolidate packaging
2025-08-15 14:07:07 -04:00
sbwalker
2ca0508030 consolidate packaging 2025-08-15 14:06:28 -04:00
Shaun Walker
8fbd50dcef Merge pull request #5499 from sbwalker/dev
resolve issue related to moving database providers to Oqtane.Server
2025-08-15 13:57:16 -04:00
sbwalker
2143660345 resolve issue related tp moving database providers to Oqtane.Server 2025-08-15 13:56:57 -04:00
Shaun Walker
8c903fbfdd Merge pull request #5496 from sbwalker/dev
update Microsoft.Data.SqlClient in AppHost
2025-08-15 13:37:49 -04:00
sbwalker
33be372348 update Microsoft.Data.SqlClient in AppHost 2025-08-15 13:37:35 -04:00
Shaun Walker
447ec3f5e6 Merge pull request #5495 from leigh-pointer/Microsoft.Data.SqlClient
Microsoft.Data.SqlClient updated
2025-08-15 13:35:00 -04:00
Leigh Pointer
a4aed69887 Microsoft.Data.SqlClient updated
Updated Microsoft.Data.SqlClient to 6.1.1
2025-08-15 19:01:03 +02:00
Leigh Pointer
4834761f64 Merge remote-tracking branch 'upstream/dev' into dev 2025-08-15 18:58:21 +02:00
Shaun Walker
bbbd6e9e3e Merge pull request #5494 from sbwalker/dev
remove unecessary using
2025-08-15 12:46:49 -04:00
sbwalker
06712faee9 remove unecessary using 2025-08-15 12:46:35 -04:00
Shaun Walker
48a90072ee Update README.md 2025-08-15 12:44:50 -04:00
Shaun Walker
0344f4d60b Update README.md 2025-08-15 12:44:31 -04:00
Shaun Walker
6a4affd5a6 Merge pull request #5493 from sbwalker/dev
add a new Visual Studio Project Template
2025-08-15 12:43:53 -04:00
sbwalker
d73e2288bb add a new Visual Studio Project Template 2025-08-15 12:43:32 -04:00
Shaun Walker
7d7500ba05 Merge pull request #5492 from sbwalker/dev
remove content from readme,md
2025-08-15 10:44:07 -04:00
sbwalker
247fc5248b remove content from readme,md 2025-08-15 10:43:52 -04:00
Shaun Walker
85fcd1ed33 Merge pull request #5490 from sbwalker/dev
improve error handling for the scenario where a connection string does not exist in appsettings.json for a tenant
2025-08-14 15:58:13 -04:00
sbwalker
4ab8f8cc25 improve error handling for the scenario where a connection string does not exist in appsettings.json for a tenant 2025-08-14 15:57:50 -04:00
Shaun Walker
ccdfe9bc26 Update appsettings.release.json 2025-08-14 15:38:38 -04:00
Shaun Walker
dc47961cc2 Update appsettings.json 2025-08-14 15:36:36 -04:00
Shaun Walker
87394cd330 Merge pull request #5489 from sbwalker/dev
migrate database providers to core framework
2025-08-14 15:20:11 -04:00
sbwalker
b5a9c32c3e migrate database providers to core framework 2025-08-14 15:19:52 -04:00
Shaun Walker
d16521f037 Merge pull request #5487 from sbwalker/dev
fix #5462 add logic to check if database already exists before calling EnsureCreated
2025-08-13 16:13:59 -04:00
sbwalker
b553b16049 fix #5462 add logic to check if database already exists before calling EnsureCreated 2025-08-13 16:13:38 -04:00
Shaun Walker
784548be57 Merge pull request #5486 from sbwalker/dev
Include support for DateTime values in RewriteValue method
2025-08-13 15:13:13 -04:00
sbwalker
cf96a80ead Include support for DateTime values in RewriteValue method 2025-08-13 15:12:58 -04:00
Shaun Walker
ede6babeaf Merge pull request #5485 from sbwalker/dev
fix compatibility issue
2025-08-13 14:55:32 -04:00
sbwalker
9a57cae4bd fix compatibility issue 2025-08-13 14:55:18 -04:00
Shaun Walker
1a296bf58c Merge pull request #5484 from sbwalker/dev
consolidate Infrastructure interface and implementation classes
2025-08-13 14:45:01 -04:00
sbwalker
e900d2f35a consolidate Infrastructure interface and implementation classes 2025-08-13 14:44:42 -04:00
Shaun Walker
69d2d3d942 Merge pull request #5483 from sbwalker/dev
add authorization convenience methods to ModuleBase
2025-08-13 08:18:33 -04:00
sbwalker
b7ff49bdb2 add authorization convenience methods to ModuleBase 2025-08-13 08:18:16 -04:00
Leigh Pointer
d0ef5d0fe3 Merge remote-tracking branch 'upstream/dev' into dev 2025-08-13 12:22:41 +02:00
Shaun Walker
3284e0f60a Merge pull request #5482 from sbwalker/dev
upgrade SQLitePCLRaw.bundle_e_sqlite3 package and add logic to release.cmd to remove android and ios client runtimes
2025-08-12 16:37:03 -04:00
sbwalker
8cec847188 upgrade SQLitePCLRaw.bundle_e_sqlite3 package and add logic to release.cmd to remove android and ios client runtimes 2025-08-12 16:36:39 -04:00
Shaun Walker
2d44644a3d Merge pull request #5481 from sbwalker/dev
bump version to 6.1.5
2025-08-12 16:08:46 -04:00
sbwalker
e32f55e433 bump version to 6.1.5 2025-08-12 16:08:30 -04:00
Shaun Walker
362c4ae272 Merge pull request #5480 from sbwalker/dev
ensure all install config settings are populated
2025-08-12 15:33:33 -04:00
sbwalker
eb8ad04557 ensure all install config settings are populated 2025-08-12 15:33:17 -04:00
Shaun Walker
d1455596c6 Merge pull request #5479 from sbwalker/dev
add InsertData(), UpdateData(), DeleteData() migration methods and improve RewriteValue() abstraction
2025-08-12 15:00:12 -04:00
sbwalker
6142bfc5db add InsertData(), UpdateData(), DeleteData() migration methods and improve RewriteValue() abstraction 2025-08-12 14:59:51 -04:00
Shaun Walker
dbda0be53b Merge pull request #5478 from sbwalker/dev
follow same pattern as core framework
2025-08-11 17:11:15 -04:00
sbwalker
bf932719b2 follow same pattern as core framework 2025-08-11 17:10:58 -04:00
Shaun Walker
60e6e33805 Merge pull request #5477 from sbwalker/dev
consolidate Service interface and implementation classes
2025-08-11 16:53:50 -04:00
sbwalker
64b8b5d3c8 consolidate Service interface and implementation classes 2025-08-11 16:53:32 -04:00
Shaun Walker
8bce40c2b8 Merge pull request #5476 from sbwalker/dev
consolidate interface and implementation classes
2025-08-11 16:36:29 -04:00
sbwalker
b3f6194fda consolidate interface and implementation classes 2025-08-11 16:36:09 -04:00
Shaun Walker
fdbf2ab0a7 Merge pull request #5475 from sbwalker/dev
fix issue with Admin Site Template
2025-08-11 16:22:40 -04:00
sbwalker
d7eb0dc509 fix issue with Admin Site Template 2025-08-11 16:22:22 -04:00
Shaun Walker
1a34bf4460 Merge pull request #5469 from sbwalker/dev
add missing delete setting API method
2025-08-07 15:07:46 -04:00
sbwalker
4cf1b5c0e7 add missing delete setting API method 2025-08-07 15:07:33 -04:00
Shaun Walker
764b883579 Merge pull request #5468 from sbwalker/dev
only hosts should be allowed to view/edit SMTP settings
2025-08-07 14:42:40 -04:00
sbwalker
3bd6767138 only hosts should be allowed to view/edit SMTP settings 2025-08-07 14:42:24 -04:00
Shaun Walker
bef9025b6c Merge pull request #5467 from sbwalker/dev
fix malformed bold tag
2025-08-07 14:32:09 -04:00
sbwalker
a37f07d20b fix malformed bold tag 2025-08-07 14:31:57 -04:00
Shaun Walker
638946b1f5 Merge pull request #5466 from sbwalker/dev
performance improvement to filter settings in database
2025-08-07 14:30:27 -04:00
sbwalker
30c869ff2a performance improvement to filter settings in database 2025-08-07 14:30:13 -04:00
Shaun Walker
2c3fda9cb5 Merge pull request #5464 from sbwalker/dev
fix #5461 - handle MinDate and MaxDate
2025-08-07 10:58:54 -04:00
sbwalker
b11a7a678c fix #5461 - handle MinDate and MaxDate 2025-08-07 10:58:33 -04:00
Shaun Walker
02011f9ce5 Merge pull request #5463 from leigh-pointer/REFsUpdate908
Updated Project Refs 9.0.8
2025-08-07 10:38:02 -04:00
Leigh Pointer
39ae6a76cd Updated Project Refs 9.0.8
# SQLitePCLRaw.bundle_e_sqlite3 was not updated.
Oqtane Framework
Project Templates Module and Theme
MAUI solution
2025-08-07 08:09:34 +02:00
Leigh Pointer
7d9b102ec4 Merge remote-tracking branch 'upstream/dev' into dev 2025-08-06 10:44:26 +02:00
Shaun Walker
31684bf7ca Merge pull request #5458 from sbwalker/dev
rolling back to SQLitePCLRaw.bundle_e_sqlite3 version 2.1.11
2025-08-04 17:18:42 -04:00
sbwalker
7b36f8d122 rolling back to SQLitePCLRaw.bundle_e_sqlite3 version 2.1.11 2025-08-04 17:18:25 -04:00
Shaun Walker
f2a0be4f57 Merge pull request #5457 from sbwalker/dev
resolve interactive page load
2025-08-04 13:09:52 -04:00
sbwalker
2cefab1c64 resolve interactive page load 2025-08-04 13:09:37 -04:00
Shaun Walker
5b4b96f065 Merge pull request #5456 from sbwalker/dev
improve FileManager performance
2025-08-04 13:06:34 -04:00
sbwalker
77949331e2 improve FileManager performance 2025-08-04 13:06:16 -04:00
Shaun Walker
4f8c4f47e2 Merge pull request #5454 from sbwalker/dev
improve FileManager performance when ShowFiles is disabled
2025-08-02 09:46:20 -04:00
sbwalker
334137454e improve FileManager performance when ShowFiles is disabled 2025-08-02 09:46:02 -04:00
Shaun Walker
af7ea3efa8 Merge pull request #5453 from sbwalker/dev
improve interactive rendering logic
2025-08-01 15:43:36 -04:00
sbwalker
6119417331 improve interactive rendering logic 2025-08-01 15:43:21 -04:00
Shaun Walker
580397a82d Merge pull request #5452 from sbwalker/dev
add active/deleted filter in User Management
2025-08-01 14:45:54 -04:00
sbwalker
23c3c47db4 add active/deleted filter in User Management 2025-08-01 14:45:40 -04:00
Shaun Walker
df3073fb12 Merge pull request #5451 from sbwalker/dev
improve broken link handling
2025-08-01 10:54:55 -04:00
sbwalker
aa9664e187 improve broken link handling 2025-08-01 10:54:40 -04:00
Shaun Walker
44f4aee55d Merge pull request #5450 from sbwalker/dev
fix AddModuleMessage not displaying messages in Interactive render mode
2025-08-01 09:15:12 -04:00
sbwalker
02861b8e01 fix AddModuleMessage not displaying messages in Interactive render mode 2025-08-01 09:14:58 -04:00
Shaun Walker
9607110381 Merge pull request #5449 from sbwalker/dev
Resolve issue where visitor cookie was not being added to HttpClient. This was because cookie values cannot contain spaces and therefore need to be Url encoded.
2025-08-01 07:52:25 -04:00
sbwalker
9ae12ff678 Resolve issue where visitor cookie was not being added to HttpClient. This was because cookie values cannot contain spaces and therefore need to be Url encoded. 2025-08-01 07:51:58 -04:00
Shaun Walker
2bcb8636ca Merge pull request #5448 from sbwalker/dev
log the logout event
2025-07-31 16:23:56 -04:00
sbwalker
4c2960eeae log the logout event 2025-07-31 16:23:40 -04:00
Shaun Walker
7e2c76e872 Merge pull request #5447 from sbwalker/dev
improve notification message when email is verified by administrator
2025-07-31 16:06:57 -04:00
sbwalker
30fcde7157 improve notification message when email is verified by administrator 2025-07-31 16:06:42 -04:00
Shaun Walker
4971d3317d Merge pull request #5446 from thabaum/6.1.5-oqtane.server-update-dependencies
Fixes #5445: Updates Oqtane.Server.csproj Package Dependencies
2025-07-31 15:54:55 -04:00
Cody
85ae7b01b8 Update Oqtane.Server.csproj Package Dependencies 2025-07-31 09:11:09 -07:00
Leigh Pointer
5b2dff254f Merge remote-tracking branch 'upstream/dev' into dev 2025-07-31 17:10:52 +02:00
Shaun Walker
9f566624fe Merge pull request #5444 from sbwalker/dev
resolve interactive rendering issue
2025-07-31 11:04:37 -04:00
sbwalker
50fa95dff9 resolve interactive rendering issue 2025-07-31 11:04:22 -04:00
Shaun Walker
752083e9eb Update README.md 2025-07-30 15:29:19 -04:00
Shaun Walker
582c7f83f7 Merge pull request #5440 from sbwalker/dev
update Azure ARM template to 6.1.4
2025-07-30 15:23:29 -04:00
sbwalker
d95104cb92 update Azure ARM template to 6.1.4 2025-07-30 15:23:16 -04:00
Shaun Walker
6c58ab4554 Merge pull request #5439 from oqtane/master
6.1.4 Release
2025-07-30 15:11:01 -04:00
Shaun Walker
085187cfac 6.1.4 Release
6.1.4 Release
2025-07-30 15:10:42 -04:00
Shaun Walker
3d0f0a5adc Merge pull request #5437 from sbwalker/dev
synchronize app.css with .NET MAUI
2025-07-30 13:40:41 -04:00
sbwalker
eae8b431ee synchronize app.css with .NET MAUI 2025-07-30 13:40:25 -04:00
Shaun Walker
e3a34446c0 Merge pull request #5436 from sbwalker/dev
synchronize interop,js with .NET MAUI
2025-07-30 13:35:56 -04:00
sbwalker
bfe57c3ac7 synchronize interop,js with .NET MAUI 2025-07-30 13:35:39 -04:00
Shaun Walker
d4001be716 Merge pull request #5435 from sbwalker/dev
fix #5364 - add ability to specify preferred Container per Pane
2025-07-30 10:43:51 -04:00
sbwalker
662a1817f2 fix #5364 - add ability to specify preferred Container per Pane 2025-07-30 10:43:36 -04:00
Shaun Walker
2c99ef412d Merge pull request #5434 from sbwalker/dev
use consistent terminology
2025-07-30 10:01:11 -04:00
sbwalker
f53ed5b13b use consistent terminology 2025-07-30 10:00:57 -04:00
Shaun Walker
b5d51838c6 Merge pull request #5433 from sbwalker/dev
allow specific time zones to be excluded
2025-07-30 09:29:56 -04:00
sbwalker
92fd70198a allow specific time zones to be excluded 2025-07-30 09:29:43 -04:00
Shaun Walker
7f1990f851 Merge pull request #5432 from sbwalker/dev
fix incorrect resource reference
2025-07-30 08:48:04 -04:00
sbwalker
797d7afc3e fix incorrect resource reference 2025-07-30 08:47:50 -04:00
Shaun Walker
c5a23cdfa0 Merge pull request #5431 from sbwalker/dev
update Oqtane theme to Bootstrap 5.3.7
2025-07-30 08:30:54 -04:00
sbwalker
906358f1f8 update Oqtane theme to Bootstrap 5.3.7 2025-07-30 08:30:40 -04:00
Shaun Walker
638f2a59c5 Merge pull request #5430 from sbwalker/dev
use margin rather than padding
2025-07-30 08:16:20 -04:00
sbwalker
cf9b4b869c use margin rather than padding 2025-07-30 08:16:07 -04:00
Shaun Walker
671c52fbbb Merge pull request #5429 from leigh-pointer/CDN-Bootstrap
Discussion #5426 updated and returned to https://cdnjs.com/
2025-07-30 08:07:52 -04:00
Leigh Pointer
6c0e2a62e7 Discussion #5426 updated and returned to https://cdnjs.com/
Updated and styles tested - reload.js needs still testing?
2025-07-30 12:53:59 +02:00
Leigh Pointer
986c9d9f72 Merge remote-tracking branch 'upstream/dev' into dev 2025-07-30 12:33:50 +02:00
Shaun Walker
1b78c9ad81 Merge pull request #5428 from sbwalker/dev
use consistent naming
2025-07-29 16:36:43 -04:00
sbwalker
7a4b98aec9 use consistent naming 2025-07-29 16:36:28 -04:00
Shaun Walker
9ef6c15014 Merge pull request #5427 from sbwalker/dev
fix #5349 - send verification email if unverified user attempts to login, add ability to enable/disable email verification per site
2025-07-29 16:20:37 -04:00
sbwalker
f4cea3fe03 fix #5349 - send verification email if unverified user attempts to login, add ability to enable/disable email verification per site 2025-07-29 16:20:07 -04:00
Shaun Walker
5dd9b1ec91 Merge pull request #5425 from sbwalker/dev
fix #5346 - deleting role should remove associated useroles
2025-07-29 09:05:54 -04:00
sbwalker
658059806b fix #5346 - deleting role should remove associated useroles 2025-07-29 09:05:37 -04:00
Shaun Walker
4f8a18451c Merge pull request #5424 from sbwalker/dev
fix #5346 - deleting role should remove associated permissions
2025-07-29 08:40:54 -04:00
sbwalker
b1770ebb76 fix #5346 - deleting role should remove associated permissions 2025-07-29 08:40:38 -04:00
Shaun Walker
6923065d86 Merge pull request #5423 from sbwalker/dev
fix #5348 - ensure time zones work consistently on all platforms
2025-07-29 08:11:56 -04:00
sbwalker
9f097521f6 fix #5348 - ensure time zones work consistently on all platforms 2025-07-29 08:11:42 -04:00
Shaun Walker
235e5c1d3a Merge pull request #5421 from sbwalker/dev
improve TimeZoneService
2025-07-28 17:00:47 -04:00
sbwalker
e179976fe8 improve TimeZoneService 2025-07-28 17:00:27 -04:00
Shaun Walker
082726b405 Merge pull request #5420 from sbwalker/dev
fix #5372 - add support for sending SMTP emails using OAuth
2025-07-28 10:26:34 -04:00
sbwalker
91c5309855 fix #5372 - add support for sending SMTP emails using OAuth 2025-07-28 10:26:18 -04:00
Shaun Walker
92be1e7a5c Merge pull request #5419 from sbwalker/dev
add OAuth support to Notification Job (#5372)
2025-07-28 09:06:55 -04:00
sbwalker
cceda1db1e add OAuth support to Notification Job (#5372) 2025-07-28 09:06:36 -04:00
Shaun Walker
a59191cea7 Merge pull request #5416 from sbwalker/dev
fix #5414 - add DelimitName database provider method to better support MigrationBuilder.Sql() operations
2025-07-25 15:22:54 -04:00
sbwalker
b0dee4a60c fix #5414 - add DelimitName database provider method to better support MigrationBuilder.Sql() operations 2025-07-25 15:22:26 -04:00
Shaun Walker
3f33f2b9df Merge pull request #5412 from sbwalker/dev
fix #5410 - allow duplicate email addresses
2025-07-23 16:40:27 -04:00
sbwalker
97116b4e0c fix #5410 - allow duplicate email addresses 2025-07-23 16:40:12 -04:00
Shaun Walker
a5f51ff9a1 Merge pull request #5411 from sbwalker/dev
localize time zone names
2025-07-23 14:52:34 -04:00
sbwalker
962488fd34 localize time zone names 2025-07-23 14:52:18 -04:00
Leigh Pointer
4db37059cd Merge remote-tracking branch 'upstream/dev' into dev 2025-07-23 14:50:24 +02:00
Shaun Walker
190d973b77 Merge pull request #5406 from leigh-pointer/Refs
Solutions References update
2025-07-22 16:14:13 -04:00
Shaun Walker
397e0b3f71 Merge pull request #5408 from sbwalker/dev
improve user experience of permissions grid
2025-07-22 16:12:48 -04:00
sbwalker
83ba9ca73e improve user experience of permissions grid 2025-07-22 16:07:52 -04:00
Shaun Walker
3d08138686 Merge pull request #5407 from sbwalker/dev
improve documentation
2025-07-22 09:23:42 -04:00
sbwalker
262fa6b99b improve documentation 2025-07-22 09:23:26 -04:00
Leigh Pointer
372db9dcfa Solutions References update
MySql.Data 9.4.0
HtmlAgilityPack 1.12.2
2025-07-22 07:45:03 +02:00
Leigh Pointer
378c68be4b Merge remote-tracking branch 'upstream/dev' into dev 2025-07-22 07:40:38 +02:00
Shaun Walker
e9dc52919c Merge pull request #5405 from sbwalker/dev
fix Control Panel to initialize extended module permissions when module is added or copied
2025-07-21 16:34:56 -04:00
sbwalker
a981dd0e97 fix Control Panel to initialize extended module permissions when module is added or copied 2025-07-21 16:34:34 -04:00
Shaun Walker
7c2775119b Merge pull request #5404 from sbwalker/dev
add new option to FileManager component to anonymize filenames during upload
2025-07-21 09:14:30 -04:00
sbwalker
0be7f1bdb5 add new option to FileManager component to anonymize filenames during upload 2025-07-21 09:14:07 -04:00
Shaun Walker
8446b9e8d5 Merge pull request #5392 from thabaum/patch-15 2025-07-15 14:28:50 -04:00
Shaun Walker
ce404668d3 Merge pull request #5391 from thabaum/6.1.4-dependencies 2025-07-15 14:28:28 -04:00
Cody
948fab50ee [FIX] #5164 – Raise z‑index for .app‑moduleactions .dropdown‑menu to 9999 2025-07-14 17:10:07 -07:00
Cody
9690f1df48 [FIX] oqtane#5164 – Raise z‑index for .app‑moduleactions .dropdown‑menu to 9999 2025-07-14 17:09:24 -07:00
Cody
5a24f87293 [FIX] #5164 ‑ Set z‑index for .dropdown‑menu in .app‑moduleactions 2025-07-14 17:07:39 -07:00
Cody
d2ff49fe73 [FIX] #5164 - Set z-index for .dropdown-menu in .app-moduleactions 2025-07-14 16:10:50 -07:00
Cody
e9035df9d2 Update Package Dependencies 2025-07-14 13:40:52 -07:00
Shaun Walker
1ddf21f4fc Merge pull request #5387 from mdmontesinos/feat-nodatime 2025-07-11 07:18:10 -04:00
David Montesinos
63d2ded038 Merge branch 'dev' into feat-nodatime 2025-07-11 09:07:12 +02:00
Shaun Walker
7b8e0e48c0 Merge pull request #5385 from leigh-pointer/907 2025-07-11 02:28:38 -04:00
David Montesinos
bb52402a17 feat: handle timezones and conversions with NodaTime 2025-07-09 12:09:00 +02:00
Leigh Pointer
13d9cb461b Update Oqtane Maui project to 9.0.7 2025-07-09 03:42:26 +02:00
Leigh Pointer
0a994afd67 Update References .NetCore 9.0.7 2025-07-09 02:52:30 +02:00
Leigh Pointer
ebca580a0b Merge remote-tracking branch 'upstream/dev' into dev 2025-07-09 01:12:17 +02:00
Shaun Walker
57a1257750 Merge pull request #5384 from sbwalker/dev
update External Login default values for Facebook OAuth2
2025-07-08 16:27:58 -04:00
sbwalker
b0c1d36bab update External Login default values for Facebook OAuth2 2025-07-08 16:27:35 -04:00
Shaun Walker
0621751968 Merge pull request #5383 from sbwalker/dev
resolve issue where IDP fails to provide email claim resulting in External Login Remote Failure due to dbo.AspNetUsers requiring a unique email value for each user
2025-07-08 16:04:37 -04:00
sbwalker
461330773a resolve issue where IDP fails to provide email claim resulting in External Login Remote Failure due to dbo.AspNetUsers requiring a unique email value for each user 2025-07-08 16:04:19 -04:00
Shaun Walker
818a97cc2c Merge pull request #5382 from sbwalker/dev
bump version to 6.1.4
2025-07-08 13:20:43 -04:00
sbwalker
17045073c8 bump version to 6.1.4 2025-07-08 13:20:28 -04:00
Shaun Walker
7a818ee698 Merge pull request #5381 from sbwalker/dev
update to .NET SDK 9.0.6
2025-07-08 13:15:10 -04:00
sbwalker
668e0cb4eb update to .NET SDK 9.0.6 2025-07-08 13:14:53 -04:00
Shaun Walker
741b16ca4e Merge pull request #5380 from sbwalker/dev
update to .NET SDK 9.0.6
2025-07-08 13:12:06 -04:00
sbwalker
85a376b17d update to .NET SDK 9.0.6 2025-07-08 13:11:52 -04:00
Shaun Walker
df86cd909c Merge pull request #5379 from sbwalker/dev
update to .NET SDK 9.0.6
2025-07-08 13:09:24 -04:00
sbwalker
ac236607f5 update to .NET SDK 9.0.6 2025-07-08 13:09:10 -04:00
Shaun Walker
19813b7eb6 Merge pull request #5378 from sbwalker/dev
remove unused variable
2025-07-07 12:42:51 -04:00
sbwalker
cb5e4e076f remove unused variable 2025-07-07 12:42:35 -04:00
Shaun Walker
48fca77f59 Merge pull request #5276 from leigh-pointer/Bootstrap
Updated to Bootstrap 5.3.5
2025-07-07 12:40:39 -04:00
Shaun Walker
76372451aa Merge pull request #5370 from zyhfish/task/fix-5363
Fix #5363: update SettingService.MergeSettings.
2025-07-07 12:40:14 -04:00
Shaun Walker
34cd197122 Merge pull request #5376 from mdmontesinos/feat-mailkit
feat: replace System.Net.Mail with MailKit (#5372)
2025-07-07 12:40:05 -04:00
David Montesinos
6b567364f9 feat: use appropriate UseSSL equivalent in MailKit 2025-07-04 14:55:02 +02:00
David Montesinos
711de49571 feat: replace System.Net.Mail with MailKit (#5372) 2025-07-04 12:55:40 +02:00
Shaun Walker
9a0f7ad83f Merge pull request #5375 from sbwalker/dev
fix #5374 Visitor Settings not returned due to change in Visitor cookie format
2025-07-03 16:45:19 -04:00
sbwalker
0d3d693799 fix #5374 Visitor Settings not returned due to change in Visitor cookie format 2025-07-03 16:44:59 -04:00
Ben
b63590d6c7 Fix #5363: update SettingService.MergeSettings. 2025-07-03 15:42:11 +08:00
Leigh Pointer
5f3a3d4d54 Merge remote-tracking branch 'upstream/dev' into Bootstrap 2025-06-13 19:58:18 +02:00
Leigh Pointer
413df647d3 Merge remote-tracking branch 'upstream/dev' into dev 2025-06-13 19:55:43 +02:00
Shaun Walker
b1a8c28283 Merge pull request #5356 from leigh-pointer/Schedular
Fix for Scheduled Jobs UI #5354
2025-06-13 08:36:47 -04:00
Leigh Pointer
1412737036 Date / Time validations
This PR ensures time fields are required when dates are set, using Oqtane validation and dynamically toggles the required attribute on time inputs when their corresponding date fields have values. Benefits:
- Uses Oqtane's validation for a polished UX.
- Reduces custom validation code.
- Aligns with our internal form logic.

- Tested across all date/time scenarios—works flawlessly!
**Testing Confirmed:**
- Date + Time Provided → Saves successfully.
- No Date + No Time → Optional (no validation).
- Date + No Time → Browser blocks submission with icon error.
2025-06-10 12:27:55 +02:00
Shaun Walker
ffb3f4fa50 Merge pull request #5353 from mdmontesinos/fix-cookieconsent
fix #5352: remove requests to cookie consent service when not enabled
2025-06-09 15:57:59 -04:00
Leigh Pointer
ff450ca43a Fix for Scheduled Jobs UI #5354
This PR addresses an issue where null date/time values could cause exceptions when processing job scheduling.
Changes Made:
- Added proper null checks for _startDate, _startTime, _endDate, _endTime, _nextDate, and _nextTime
- Improved parsing safety for _retentionHistory using int.TryParse()
- Added validation to fail early with meaningful error messages

Impact:

Prevents NullReferenceException and InvalidOperationException when date/time fields are missing
2025-06-09 10:29:43 +02:00
David Montesinos
d4f0805108 fix #5352: remove requests to cookie consent service when not enabled 2025-06-06 10:05:40 +02:00
Leigh Pointer
a1011ed709 Merge remote-tracking branch 'upstream/dev' into dev 2025-06-05 17:03:48 +02:00
Shaun Walker
64ce69d1c7 Merge pull request #5351 from sbwalker/dev
stop gap fix to mitigate date conversion exceptions on WebAssembly
2025-06-05 10:38:51 -04:00
sbwalker
ca3cb48091 Merge branch 'dev' of https://github.com/sbwalker/oqtane.framework into dev 2025-06-05 10:37:31 -04:00
sbwalker
85085bf4c7 stop gap fix to mitigate date conversion exceptions on WebAssembly 2025-06-05 10:37:25 -04:00
Leigh Pointer
71be6d4ded Merge remote-tracking branch 'upstream/dev' into dev 2025-06-05 15:46:15 +02:00
Shaun Walker
873af6b598 Merge pull request #5349 from leigh-pointer/References
Server References Updated
2025-06-05 09:32:34 -04:00
Shaun Walker
c423895f31 Merge pull request #5350 from sbwalker/dev
rendering optimizations
2025-06-05 09:32:12 -04:00
sbwalker
4418e27c29 rendering optimizations 2025-06-05 09:31:54 -04:00
Leigh Pointer
f776977af8 Server References Updated
update SixLabors.ImageSharp
update Swashbuckle.AspNetCore
2025-06-04 13:28:49 +02:00
Leigh Pointer
f586401a14 Merge remote-tracking branch 'upstream/dev' into dev 2025-06-03 15:25:00 +02:00
Leigh Pointer
c13ce3d0f1 Update Index.razor
Deprecated .text-muted will be replaced by .text-body-secondary in v6.
2025-06-03 15:24:43 +02:00
Leigh Pointer
2c4c669ea2 Merge remote-tracking branch 'upstream/dev' into Bootstrap 2025-05-30 16:06:19 +02:00
Shaun Walker
29fe3dfd0b Merge pull request #5344 from sbwalker/dev
update Azure ARM template to 6.1.3
2025-05-29 17:05:04 -04:00
sbwalker
985e50d415 update Azure ARM template to 6.1.3 2025-05-29 17:04:45 -04:00
Shaun Walker
11150b6a10 Update README.md 2025-05-29 17:03:20 -04:00
Shaun Walker
c499acdc4a Merge pull request #5342 from oqtane/master
Merge pull request #5341 from oqtane/dev
2025-05-29 15:59:32 -04:00
Shaun Walker
b24e3252d9 Merge pull request #5341 from oqtane/dev
6.1.3 Release
2025-05-29 15:58:55 -04:00
Shaun Walker
e15787b1e4 Merge pull request #5340 from sbwalker/dev
change id for header/footer
2025-05-29 15:04:28 -04:00
sbwalker
d5f19d97e2 change id for header/footer 2025-05-29 15:04:12 -04:00
Shaun Walker
5543a4aeed Merge pull request #5339 from sbwalker/dev
fix #5329 - clear Options after updating User Settings
2025-05-29 11:53:29 -04:00
sbwalker
9c333232e2 fix #5329 - clear Options after updating User Settings 2025-05-29 11:53:14 -04:00
Leigh Pointer
fa384cb6f3 Merge remote-tracking branch 'upstream/dev' into dev 2025-05-28 19:41:13 +02:00
Shaun Walker
d52b95ea23 Merge pull request #5333 from leigh-pointer/TokenReplace
Fix for ModuleBase ReplaceTokens #5332
2025-05-28 13:11:28 -04:00
Leigh Pointer
ef4fbcbb8a Update ModuleBase.cs
This method replaces all tokens in the format [Object:Property] or [Object:SubObject:Property] within a string.
Efficient string parsing and reflection ensure flexibility with performance.
It supports deeply nested properties, optional default fallback values (e.g. [PageState:User:Email|default@email.com]), and uses caching to optimize repeated token resolution without regex.
2025-05-28 17:30:19 +02:00
Shaun Walker
aa454b411f Merge pull request #5335 from thabaum/Update-Swashbuckle.AspNetCore-Package-Dependency-to-8.1.2
Fixes #5331: Updates Swashbuckle.AspNetCore Package Dependency to 8.1.2
2025-05-28 08:23:39 -04:00
Cody
543e9339c7 Update Swashbuckle.AspNetCore Package Dependency to 8.1.2 2025-05-25 09:34:09 -07:00
Leigh Pointer
7fff5c0d18 Fix for ModuleBase ReplaceTokens #5332
Replaced the ReplaceTokens logic to replace all tokens in the string
2025-05-25 10:55:49 +02:00
Leigh Pointer
05db1bcbfb Merge remote-tracking branch 'upstream/dev' into dev 2025-05-20 11:24:04 +02:00
Shaun Walker
fa79f3f6fa Merge pull request #5326 from sbwalker/dev
fix #5205 add support for inheritance when loading Resources from ModuleBase or ThemeBase
2025-05-19 21:01:02 -07:00
sbwalker
c098839881 fix #5205 add support for inheritance when loading Resources from ModuleBase or ThemeBase 2025-05-19 21:00:35 -07:00
Shaun Walker
8d0d88c1b9 Merge pull request #5325 from sbwalker/dev
ensure Content folder is empty when packaging
2025-05-19 18:32:42 -04:00
sbwalker
2b6ba0f410 ensure Content folder is empty when packaging 2025-05-19 15:32:27 -07:00
Shaun Walker
11235009c0 Merge pull request #5324 from sbwalker/dev
imprvoe help text
2025-05-19 18:15:03 -04:00
sbwalker
4b05f7fdad imprvoe help text 2025-05-19 15:14:49 -07:00
Leigh Pointer
bdd6d9781c Merge remote-tracking branch 'upstream/dev' into dev 2025-05-19 11:24:47 +02:00
Shaun Walker
338b0ae509 Merge pull request #5320 from sbwalker/dev
use consistent authorization method
2025-05-16 12:11:16 -04:00
sbwalker
a437082952 use consistent authorization method 2025-05-16 12:11:03 -04:00
Shaun Walker
ca9aba7b3b Merge pull request #5319 from sbwalker/dev
improve comment
2025-05-16 11:53:17 -04:00
sbwalker
fe9f189734 improve comment 2025-05-16 11:53:04 -04:00
Shaun Walker
018ac612f4 Merge pull request #5318 from sbwalker/dev
improve messaging
2025-05-16 11:47:06 -04:00
sbwalker
5bde40ec2b improve messaging 2025-05-16 11:46:53 -04:00
Shaun Walker
4d5780c192 Merge pull request #5317 from sbwalker/dev
Fix #4789 - allow user email verification to be managed by administrator
2025-05-16 11:13:20 -04:00
sbwalker
ff6a810ad5 Fix #4789 - allow user email verification to be managed by administrator 2025-05-16 11:13:03 -04:00
Shaun Walker
feec01ba00 Merge pull request #5316 from sbwalker/dev
fix spelling mistake
2025-05-16 09:40:10 -04:00
sbwalker
1f05d12ef5 fix spelling mistake 2025-05-16 09:39:57 -04:00
Shaun Walker
31aba14507 Merge pull request #5315 from sbwalker/dev
fix initialization issue related to time zones
2025-05-16 09:09:21 -04:00
sbwalker
bbd6f13f36 fix initialization issue related to time zones 2025-05-16 09:09:07 -04:00
Shaun Walker
68edbbbdb9 Merge pull request #5314 from sbwalker/dev
improve filename validation in module content export
2025-05-16 08:26:04 -04:00
sbwalker
eb5a0dc1c9 improve filename validation in module content export 2025-05-16 08:25:50 -04:00
Leigh Pointer
d23a5ad91b Merge remote-tracking branch 'upstream/dev' into dev 2025-05-16 12:49:44 +02:00
Shaun Walker
7cea4f1792 Merge pull request #5312 from sbwalker/dev
update module export resource info
2025-05-15 11:06:20 -04:00
sbwalker
c57c6abb1b update module export resource info 2025-05-15 11:06:04 -04:00
Shaun Walker
a25b706c7b Merge pull request #5311 from sbwalker/dev
allow filename to be provided during module export
2025-05-15 10:59:10 -04:00
sbwalker
5d077e843d allow filename to be provided during module export 2025-05-15 10:58:55 -04:00
Shaun Walker
65bf3e9899 Merge pull request #5310 from sbwalker/dev
allow module import from a file
2025-05-15 09:34:37 -04:00
sbwalker
51ba3a01f5 allow module import from a file 2025-05-15 09:34:19 -04:00
Shaun Walker
f9ca611b8b Merge pull request #5309 from sbwalker/dev
improve module export so that content can be saved to a file
2025-05-15 08:56:37 -04:00
sbwalker
a49b8728fd improve module export so that content can be saved to a file 2025-05-15 08:56:21 -04:00
Leigh Pointer
018737c42a Merge remote-tracking branch 'upstream/dev' into Bootstrap 2025-05-15 11:52:51 +02:00
Leigh Pointer
a50e179744 Merge remote-tracking branch 'upstream/dev' into dev 2025-05-15 11:52:15 +02:00
Shaun Walker
9234b91089 Merge pull request #5306 from sbwalker/dev
fix #5200 - sort folders alphabetically, display folders hierarchically
2025-05-14 15:52:04 -04:00
sbwalker
f3fcef52dd fix #5200 - sort folders alphabetically, display folders hierarchically 2025-05-14 15:51:51 -04:00
Shaun Walker
7f8b741981 Merge pull request #5305 from sbwalker/dev
fix issue with module header/footer
2025-05-14 14:20:54 -04:00
sbwalker
f1791a709c fix issue with module header/footer 2025-05-14 14:20:44 -04:00
Shaun Walker
30307fb05e Merge pull request #5304 from sbwalker/dev
support for module header and footer content
2025-05-14 12:18:51 -04:00
sbwalker
57d443be8d support for module header and footer content 2025-05-14 12:18:37 -04:00
Shaun Walker
84844c5043 Merge pull request #5303 from sbwalker/dev
move ConfigureOqtaneAssemblies to occur before UseEndpoints
2025-05-14 11:13:12 -04:00
sbwalker
9000f05961 move ConfigureOqtaneAssemblies to occur before UseEndpoints 2025-05-14 11:12:58 -04:00
Shaun Walker
6bef9b5c6e Merge pull request #5302 from sbwalker/dev
update default templates to .NET SDK 9.0.5
2025-05-13 16:52:51 -04:00
sbwalker
ffef1f4820 update default templates to .NET SDK 9.0.5 2025-05-13 16:52:39 -04:00
Shaun Walker
10c7bdbcaa Merge pull request #5301 from sbwalker/dev
upgrade to .NET SDK 9.0.5
2025-05-13 16:49:59 -04:00
sbwalker
e8f9888a41 upgrade to .NET SDK 9.0.5 2025-05-13 16:49:46 -04:00
Shaun Walker
8bac702be6 Merge pull request #5300 from sbwalker/dev
rollback change which moved ConfigureOqtaneAssemblies
2025-05-13 16:39:08 -04:00
sbwalker
128bcecfe3 rollback change which moved ConfigureOqtaneAssemblies(env); 2025-05-13 16:38:48 -04:00
Shaun Walker
1390b3c489 Merge pull request #5299 from sbwalker/dev
fix #5398 - editing page permissions
2025-05-13 15:49:30 -04:00
sbwalker
a0f41341ac fix #5398 - editing page permissions 2025-05-13 15:49:16 -04:00
Shaun Walker
8ffa7ef7ff Merge pull request #5297 from sbwalker/dev
adding time zone support to admin modules
2025-05-13 13:55:15 -04:00
sbwalker
deb4607081 adding time zone support to admin modules 2025-05-13 13:55:01 -04:00
Shaun Walker
49c62f80e8 Merge pull request #5296 from sbwalker/dev
display local datetimes in the Job Scheduler (using time zones)
2025-05-13 11:29:40 -04:00
sbwalker
139793f3c0 display local datetimes in the Job Scheduler (using time zones) 2025-05-13 11:29:26 -04:00
Shaun Walker
f237cb9655 Merge pull request #5295 from sbwalker/dev
add time zone support for sites and users
2025-05-13 09:24:33 -04:00
sbwalker
9f18c460d8 add time zone support for sites and users 2025-05-13 09:24:17 -04:00
Shaun Walker
306a41b442 Merge pull request #5293 from sbwalker/dev
fix #5292 - fix External Login Provider Info link
2025-05-12 11:32:42 -04:00
sbwalker
b53f54295d fix #5292 - fix External Login Provider Info link 2025-05-12 11:32:27 -04:00
Shaun Walker
7e4f066694 Merge pull request #5291 from sbwalker/dev
fix #5287 - allow deletion of folder which contains files
2025-05-12 08:42:12 -04:00
sbwalker
90d72489d9 fix #5287 - allow deletion of folder which contains files 2025-05-12 08:41:57 -04:00
Shaun Walker
045c455324 Merge pull request #5286 from sbwalker/dev
update version to 6.1.3
2025-05-08 16:09:12 -04:00
sbwalker
60da903360 update version to 6.1.3 2025-05-08 16:09:00 -04:00
Shaun Walker
6d2a71f37e Merge pull request #5283 from thabaum/update-6.1.3
Fixes #5267: Updates Project Dependencies and Version to 6.1.3
2025-05-08 16:07:48 -04:00
Shaun Walker
c8f60a12a4 Merge pull request #5277 from ohba-ikuo/dev
Modify the module's server-side resource path.
2025-05-07 17:27:15 -04:00
Shaun Walker
11b2d3aa43 Merge pull request #5284 from sbwalker/dev
change Synchronize button to Check For Updates to improve clarity
2025-05-07 17:12:26 -04:00
sbwalker
3d9c81d850 change Synchronize button to Check For Updates to improve clarity 2025-05-07 17:12:14 -04:00
Cody
8ccb1a24f8 Update Version to 6.1.3 2025-05-07 10:25:27 -07:00
Cody
48c6796128 Update Version to 6.1.3 2025-05-07 10:24:36 -07:00
Cody
fc403f920b Update Version to 6.1.3 2025-05-07 10:24:13 -07:00
Cody
ca19496b5c Update Version to 6.1.3 2025-05-07 10:23:32 -07:00
Cody
0ae38f8a40 Update Version to 6.1.3 2025-05-07 10:23:11 -07:00
Cody
ad868ba841 Update Version to 6.1.3 2025-05-07 10:22:47 -07:00
Cody
f2aa39aa85 Update Version to 6.1.3 2025-05-07 10:22:04 -07:00
Cody
e76e0fc351 Update Version to 6.1.3 2025-05-07 10:20:52 -07:00
Cody
a348913888 Update Version to 6.1.3 2025-05-07 10:20:15 -07:00
Cody
5507006c53 Update Version to 6.1.3 2025-05-07 10:19:05 -07:00
Cody
994429f098 Update Version to 6.1.3 2025-05-07 10:18:40 -07:00
Cody
8efdcb9c49 Update Version to 6.1.3 2025-05-07 10:17:54 -07:00
Cody
db9a40db2b Update Version to 6.1.3 2025-05-07 10:17:17 -07:00
Cody
25667499e6 Update Package Dependencies & Version to 6.1.3 2025-05-07 10:16:38 -07:00
Cody
a728cd2d91 Update Package Dependencies & Version to 6.1.3 2025-05-07 10:14:12 -07:00
Cody
3f5f3ef10b Update Version to 6.1.3 2025-05-07 10:10:58 -07:00
Leigh Pointer
3811b8f0c0 Theme Template updated 2025-05-07 11:46:07 +02:00
Ikuo Ohba
0d708124c2 Undo Oqtane.Server.csproj 2025-05-07 08:31:34 +09:00
Ikuo Ohba
d31f73df14 Merge branch 'oqtane:dev' into dev 2025-05-07 06:20:48 +09:00
Shaun Walker
3fed45438b Merge pull request #5281 from thabaum/HtmlText.cs-Unused-Namespaces
Fixes #5280: Remove Unused Namespaces from HtmlText.cs in HtmlText Module
2025-05-06 16:50:10 -04:00
Cody
8aa967fa1b Remove Unnecessary Namespaces
Removes Unnecessary Namespaces 'System' and 'System.ComponentModel.DataAnnotations.Schema;'.
2025-05-06 13:29:26 -07:00
Ikuo Ohba
6eaa3e342c Merge branch 'dev' of https://github.com/ohba-ikuo/oqtane.framework into dev 2025-05-02 23:45:18 +09:00
Ikuo Ohba
6fc9e60f62 fixed serverside resource path 2025-05-02 23:45:13 +09:00
Leigh Pointer
d81514e9be Update for Blazor Theme 2025-05-02 12:19:58 +02:00
Leigh Pointer
874d9f32a9 Updated fBootstrap for Blazor theme 2025-05-02 12:18:45 +02:00
Leigh Pointer
14b0d7abf0 Updated to Bootstrap 5
Updated to Bootstrap 5.3.5
Update bootswatch Cyborg to 5.3.5 using https://cdn.jsdelivr.net because it is not available at https://cdnjs.com/libraries
2025-05-02 12:16:55 +02:00
Shaun Walker
c39ffcf51c Merge pull request #5275 from sbwalker/dev
add new Register Url and Profile Url options to User Management / Settings
2025-05-01 23:33:10 -04:00
sbwalker
6f60a91f4c add new Register Url and Profile Url options to User Management / Settings 2025-05-01 23:32:37 -04:00
Shaun Walker
8031df6f28 Merge pull request #5274 from sbwalker/dev
use new GetSettingValue() method
2025-04-30 14:35:11 -04:00
sbwalker
da1e859fda use new GetSettingValue() method 2025-04-30 14:34:54 -04:00
Shaun Walker
8d4d25f1d1 Merge pull request #5273 from sbwalker/dev
use new GetSettingValue() method
2025-04-30 14:18:44 -04:00
sbwalker
6aff27778d use new GetSettingValue() method 2025-04-30 14:18:29 -04:00
Shaun Walker
ca2dcbfec0 Merge pull request #5272 from sbwalker/dev
remove unecessary using statment
2025-04-30 13:55:24 -04:00
sbwalker
24b666a382 remove unecessary using statment 2025-04-30 13:55:11 -04:00
Shaun Walker
9e34295529 Merge pull request #5270 from leigh-pointer/ModBase
GetUrlParameters crash
2025-04-30 13:47:21 -04:00
Shaun Walker
10c55d056b Merge pull request #5271 from sbwalker/dev
resolve issue with host setting overrides
2025-04-30 13:47:06 -04:00
sbwalker
753ab3bdd7 resolve issue with host setting overrides 2025-04-30 13:46:52 -04:00
Leigh Pointer
feee8def6f GetUrlParameters crash
The _urlparametersstate variable is not initialized so in GetUrlParameters it causes a crash
2025-04-29 09:50:15 +02:00
Shaun Walker
c208f12f8c Merge pull request #5266 from sbwalker/dev
add a convenience method to get a setting value server-side
2025-04-28 12:43:04 -04:00
sbwalker
dc926bf838 add a convenience method to get a setting value server-side 2025-04-28 12:42:50 -04:00
Shaun Walker
55a76b5204 Merge pull request #5265 from sbwalker/dev
fix #5229 - move IServerStartup.Configure execution until later so that it is possible to register custom endpoints
2025-04-28 12:35:49 -04:00
sbwalker
53b837e763 fix #5229 - move IServerStartup.Configure execution until later so that it is possible to register custom endpoints 2025-04-28 12:34:48 -04:00
Shaun Walker
3a551cdf25 Merge pull request #5257 from leigh-pointer/AddMDfiles
Updated UploadableFiles constant
2025-04-22 17:00:03 -04:00
Shaun Walker
c0c7f87dc9 Merge pull request #5256 from leigh-pointer/Packages
Packages updated
2025-04-22 16:59:49 -04:00
Leigh Pointer
ac77fd138b Updated UploadableFiles constant
Updated UploadableFiles constant to allow for Markdown files to be uploaded.
2025-04-22 10:08:20 +02:00
Leigh Pointer
30d6e9d67c Merge branch 'dev' into Packages 2025-04-22 09:13:15 +02:00
Leigh Pointer
47db4334a1 Packages updated
MySql.Data to 9.3.0
HtmlAgilityPack to 1.12.1
washbuckle.AspNetCore to 8.1.1
2025-04-22 09:11:53 +02:00
Shaun Walker
fce97179e1 Merge pull request #5255 from sbwalker/dev
url mapping improvements
2025-04-21 15:14:52 -04:00
sbwalker
4f16cd2d01 url mapping improvements 2025-04-21 15:14:39 -04:00
Shaun Walker
fa587691b1 Merge pull request #5254 from sbwalker/dev
improve validation in Url Mapping
2025-04-21 14:14:03 -04:00
sbwalker
e0044658f9 improve validation in Url Mapping 2025-04-21 14:13:49 -04:00
Shaun Walker
53de1ddb36 Merge pull request #5253 from mdmontesinos/files-optimization
Files server optimization
2025-04-21 13:57:41 -04:00
David Montesinos
da7b046092 Remove extra using 2025-04-21 18:47:34 +02:00
David Montesinos
d888d83a98 Simplify files etag calculation 2025-04-21 18:44:16 +02:00
David Montesinos
430f83e8e9 Only compute hash when file has query string 2025-04-21 16:46:55 +02:00
David Montesinos
e7acd14faa Replace MD5 hash with a longer simple hash 2025-04-21 15:51:25 +02:00
David Montesinos
1b00fa74bc Compute file server etag with MD5 and always include ModifiedOn 2025-04-21 11:14:24 +02:00
David Montesinos
4d572d8173 Allow earlier return in files server 2025-04-21 10:48:48 +02:00
Shaun Walker
dbda85d8d9 Merge pull request #5248 from sbwalker/dev
UX improvements for System Update
2025-04-15 09:20:35 -04:00
sbwalker
95cb5dd66c UX improvements for System Update 2025-04-15 09:20:18 -04:00
Shaun Walker
f64e1c3a6a Merge pull request #5245 from sbwalker/dev
.NET MAUI client was changed from 0.0.0.0 to 0.0.0.1 in .NET 9
2025-04-11 15:54:17 -04:00
sbwalker
26a686c412 .NET MAUI client was changed from 0.0.0.0 to 0.0.0.1 in .NET 9 2025-04-11 15:54:02 -04:00
Shaun Walker
2505383f53 Merge pull request #5244 from leigh-pointer/Swash
Swagger Updated to latest
2025-04-11 09:03:29 -04:00
Leigh Pointer
1a1e9ac6be Swagger Updated to latest
Swashbuckle.AspNetCore update from 8.1.0 > 8.1.1
2025-04-11 09:24:18 +02:00
Shaun Walker
7f20a3179e Merge pull request #5241 from sbwalker/dev
fix issue with new UserProfile parameters
2025-04-10 14:36:57 -04:00
sbwalker
46431f0187 fix issue with new UserProfile parameters 2025-04-10 14:36:42 -04:00
Shaun Walker
1ff8ec78c9 Merge pull request #5240 from sbwalker/dev
backup parameter needs to be backward compatible
2025-04-10 12:27:39 -04:00
sbwalker
7840230c62 backup parameter needs to be backward compatible 2025-04-10 12:27:21 -04:00
Shaun Walker
523db0a005 Merge pull request #5239 from sbwalker/dev
update Deploy To Azure to the 6.1.2 release
2025-04-10 12:04:40 -04:00
sbwalker
cc906d49ba update Deploy To Azure to the 6.1.2 release 2025-04-10 12:04:26 -04:00
Shaun Walker
fc23af89d3 Update README.md 2025-04-10 11:54:58 -04:00
Shaun Walker
5d8829ba63 Merge pull request #5238 from oqtane/master
6.1.2 Release
2025-04-10 11:48:58 -04:00
Shaun Walker
31ccd80894 Merge pull request #5237 from oqtane/dev
6.1.2 Release
2025-04-10 11:48:36 -04:00
Shaun Walker
bac2234616 Delete Oqtane.Server/wwwroot/Packages/Oqtane.Database.Sqlite.nupkg 2025-04-10 07:49:01 -04:00
Shaun Walker
bd61db76a3 Delete Oqtane.Server/wwwroot/Packages/Oqtane.Database.SqlServer.nupkg 2025-04-10 07:48:52 -04:00
Shaun Walker
bc99e3b992 Delete Oqtane.Server/wwwroot/Packages/Oqtane.Database.MySQL.nupkg 2025-04-10 07:48:42 -04:00
Shaun Walker
b7314b0813 Delete Oqtane.Server/wwwroot/Packages/Oqtane.Database.PostgreSQL.nupkg 2025-04-10 07:48:31 -04:00
Shaun Walker
4759bd569f Merge pull request #5235 from sbwalker/dev
fix incorrect path in theme template
2025-04-09 17:21:36 -04:00
sbwalker
b88c28f864 fix incorrect path in theme template 2025-04-09 17:21:23 -04:00
Shaun Walker
774ccb05f8 Merge pull request #5234 from sbwalker/dev
removing ShutdownTimeout specification as it was changed in .NET 7 to 30 seconds (https://github.com/dotnet/runtime/pull/63712)
2025-04-09 14:58:56 -04:00
sbwalker
0ac48cba34 removing ShutdownTimeout specification as it was changed in .NET 7 to 30 seconds (https://github.com/dotnet/runtime/pull/63712) 2025-04-09 14:58:30 -04:00
Shaun Walker
e36880fe3a Merge pull request #5233 from sbwalker/dev
prepare for 6.1.2 release
2025-04-09 11:46:30 -04:00
sbwalker
713cf5de2c prepare for 6.1.2 release 2025-04-09 11:46:16 -04:00
Shaun Walker
0fa336411f Merge pull request #5232 from sbwalker/dev
update to .NET 9.0.4
2025-04-09 11:41:08 -04:00
sbwalker
8ebdb09d68 update to .NET 9.0.4 2025-04-09 11:40:54 -04:00
Shaun Walker
40bc53001e Merge pull request #5231 from sbwalker/dev
improve sitemap detection in robots.txt
2025-04-09 11:26:53 -04:00
sbwalker
b1656d1eea improve sitemap detection in robots.txt 2025-04-09 11:26:33 -04:00
Shaun Walker
7aa54bf979 Merge pull request #5230 from sbwalker/dev
resolve issue with host role support  in external login
2025-04-09 10:55:32 -04:00
sbwalker
231f9bca84 resolve issue with host role support in external login 2025-04-09 10:55:16 -04:00
Shaun Walker
e4f8596c19 Merge pull request #5227 from sbwalker/dev
fix #5223 - allow robots.txt to be customized for each site
2025-04-08 09:23:35 -04:00
sbwalker
020b7233d0 fix #5223 - allow robots.txt to be customized for each site 2025-04-08 09:23:22 -04:00
Shaun Walker
85fc0b3e2f Merge pull request #5226 from sbwalker/dev
optimize the System Update process
2025-04-07 13:19:07 -04:00
sbwalker
5dcc7c14f3 optimize the System Update process 2025-04-07 13:18:52 -04:00
Shaun Walker
7993d27b11 Merge pull request #5224 from sbwalker/dev
added new Azure SQL database provider
2025-04-07 10:48:20 -04:00
sbwalker
1f8c54ce74 added new Azure SQL database provider 2025-04-07 10:48:02 -04:00
Shaun Walker
73a414a34b Merge pull request #5221 from sbwalker/dev
improve help text
2025-04-02 09:47:31 -04:00
sbwalker
8fa19c4a51 improve help text 2025-04-02 09:47:16 -04:00
Shaun Walker
0667ae3e15 Merge pull request #5220 from sbwalker/dev
update help text
2025-04-02 09:36:49 -04:00
sbwalker
db1d00cd07 update help text 2025-04-02 09:36:32 -04:00
Shaun Walker
b27f092bef Merge pull request #5219 from sbwalker/dev
use dynamic .NET major version value
2025-04-01 15:29:26 -04:00
sbwalker
4eaea8e586 use dynamic .NET major version value 2025-04-01 15:29:10 -04:00
Shaun Walker
89cd7d3bbb Update README.md 2025-04-01 14:30:49 -04:00
Shaun Walker
2fff1d8d21 Merge pull request #5218 from sbwalker/dev
removing connection string section
2025-04-01 13:55:09 -04:00
sbwalker
850631f00e removing connection string section 2025-04-01 13:54:39 -04:00
Shaun Walker
1cea8846cf Merge pull request #5217 from sbwalker/dev
fix azuredeploy
2025-04-01 11:04:02 -04:00
sbwalker
af48a48559 fix azuredeploy 2025-04-01 11:03:46 -04:00
Shaun Walker
655c1762aa Merge pull request #5216 from sbwalker/dev
azuredeploy changes to use ZIP Deploy
2025-04-01 10:56:47 -04:00
sbwalker
f706ccfd87 new version using ZIP Deploy 2025-04-01 10:56:04 -04:00
Shaun Walker
71e4c7f117 Merge pull request #5214 from sbwalker/dev
remove .deployment file as we are deploying from a package rather than from source code
2025-03-31 16:22:08 -04:00
sbwalker
ad6182f4bd remove .deployment file as we are deploying from a package rather than from source code 2025-03-31 16:21:45 -04:00
Shaun Walker
86bf0f65b0 Merge pull request #5213 from sbwalker/dev
modifications to use WEBSITE_RUN_FROM_PACKAGE
2025-03-31 16:06:24 -04:00
sbwalker
7742f7747d modifications to use WEBSITE_RUN_FROM_PACKAGE 2025-03-31 16:06:08 -04:00
Shaun Walker
eb998c41f2 Merge pull request #5212 from sbwalker/dev
fix #4929 deploy to azure
2025-03-31 13:59:12 -04:00
sbwalker
657bd7c97c fix #4929 deploy to azure 2025-03-31 13:58:03 -04:00
Shaun Walker
c8286148c1 Merge pull request #5211 from sbwalker/dev
fix #5194 - improve performance of retrieving scheduled job logs
2025-03-31 13:16:52 -04:00
sbwalker
e6ba2cce62 fix #5194 - improve performance of retrieving scheduled job logs 2025-03-31 13:16:35 -04:00
Shaun Walker
6105ff44b4 Merge pull request #5210 from sbwalker/dev
fix #5207 add support for username and displayname in permissions grid
2025-03-31 10:04:43 -04:00
sbwalker
72da77be01 fix #5207 add support for username and displayname in permissions grid 2025-03-31 10:04:26 -04:00
Shaun Walker
4c29b31f1b Merge pull request #5209 from sbwalker/dev
delete files before deleting folder
2025-03-31 08:58:39 -04:00
sbwalker
6e640108ed delete files before deleting folder 2025-03-31 08:58:23 -04:00
Shaun Walker
157322441d Merge pull request #5206 from zyhfish/task/fix-5205
Fix #5205: specific the date time as UTC kind.
2025-03-31 08:40:28 -04:00
Shaun Walker
61d967e6af Merge pull request #5208 from sbwalker/dev
allow custom urls in UserProfile component
2025-03-31 08:38:46 -04:00
sbwalker
99f2158e55 allow custom urls in UserProfile component 2025-03-31 08:38:30 -04:00
Ben
1cba78cc4e Fix #5205: specific the date time as UTC kind. 2025-03-29 09:29:49 +08:00
Shaun Walker
1770c1ee11 Merge pull request #5201 from sbwalker/dev
include external login support for host role
2025-03-26 17:11:52 -04:00
sbwalker
a57fbea0cc include external login support for host role 2025-03-26 17:11:29 -04:00
Shaun Walker
f0c27c83f1 Merge pull request #5197 from zyhfish/task/clean-build
suppress build warnings.
2025-03-26 11:16:47 -04:00
Ben
7873ca564c supress build warnings. 2025-03-26 08:12:10 +08:00
Shaun Walker
5ebc1fec24 Merge pull request #5195 from zyhfish/task/fix-5191
Fix #5191: trigger event when folder changed.
2025-03-25 19:46:24 -04:00
Shaun Walker
f2559b7d4d Merge pull request #5196 from sbwalker/dev
fix #5193 - prevent scheduled jobs from blocking startup
2025-03-25 19:07:24 -04:00
sbwalker
1ee92a248e fix #5193 - prevent scheduled jobs from blocking startup 2025-03-25 19:07:01 -04:00
Ben
8376f98f21 Fix #5191: trigger event when folder changed. 2025-03-25 22:23:51 +08:00
Shaun Walker
810a3e0171 Merge pull request #5188 from sbwalker/dev
prevent stylesheet resources from being duplicated
2025-03-21 17:34:21 -04:00
sbwalker
2eac9c3795 prevent stylesheet resources from being duplicated 2025-03-21 17:34:07 -04:00
Shaun Walker
75f2425668 Merge pull request #5187 from sbwalker/dev
remove unnecessary using statements
2025-03-21 10:10:32 -04:00
sbwalker
2dd1d7e926 remove unnecessary using statements 2025-03-21 10:10:19 -04:00
Shaun Walker
5bb05a0a51 Merge pull request #5185 from sbwalker/dev
fix page order for new Privacy and Terms pages
2025-03-21 08:19:26 -04:00
sbwalker
bc2c5b00c6 fix page order for new Privacy and Terms pages 2025-03-21 08:19:09 -04:00
Shaun Walker
09f5e158dd Merge pull request #5181 from sbwalker/dev
add ability to Synchronize local modules and themes with Marketplace
2025-03-19 14:37:50 -04:00
sbwalker
4656471a0a add ability to Synchronize local modules and themes with Marketplace 2025-03-19 14:37:36 -04:00
Shaun Walker
69d58a4273 Merge pull request #5179 from leigh-pointer/SwashbuckleUpdate8
Swashbuckle Update
2025-03-19 08:42:40 -04:00
Leigh Pointer
53a27677d4 Swashbuckle Update
Update Swashbuckle  to version 8.0
2025-03-19 12:07:15 +01:00
Shaun Walker
f243ad0348 Merge pull request #5178 from sbwalker/dev
add caching support for ImageUrl
2025-03-18 14:29:23 -04:00
sbwalker
b4ce6bbb42 add caching support for ImageUrl 2025-03-18 14:29:09 -04:00
Shaun Walker
fa32937045 Merge pull request #5177 from sbwalker/dev
MySql.Data is still required for raw query operations
2025-03-18 09:24:53 -04:00
sbwalker
812e5f3c8e MySql.Data is still required for raw query operations 2025-03-18 09:24:39 -04:00
Shaun Walker
e2981e802c Merge pull request #5176 from sbwalker/dev
fix #5173 - MySQL Database Provider not incuding MySqlConnector dependency
2025-03-18 09:08:07 -04:00
sbwalker
4ae4705c73 fix #5173 - MySQL Database Provider not incuding MySqlConnector dependency 2025-03-18 09:07:23 -04:00
Shaun Walker
fbf4b12713 Merge pull request #5168 from zyhfish/task/fix-cookie-consent-layout
adjust the cookie consent layout in small screen.
2025-03-17 13:45:14 -04:00
Shaun Walker
e4ece3e0dc Merge pull request #5174 from sbwalker/dev
notifications should only convert line breaks to HTML for plain text messages
2025-03-17 13:45:02 -04:00
sbwalker
9f231421be notifications should only convert line breaks to HTML for plain text messages 2025-03-17 13:44:40 -04:00
Ben
b4fdbb5e48 adjust the layout in small screen. 2025-03-13 21:54:43 +08:00
Ben
fbf62ca30d adjust the cookie consent layout in small screen. 2025-03-13 20:54:50 +08:00
Shaun Walker
05d2096fb8 Update README.md 2025-03-12 14:34:31 -04:00
Shaun Walker
7683af81bc Update README.md 2025-03-12 14:22:43 -04:00
Shaun Walker
bad10b3812 6.1.1 Release
6.1.1 Release
2025-03-12 14:21:41 -04:00
Shaun Walker
9f9522c2ed 6.1.1 Release
6.1.1 Release
2025-03-12 14:21:15 -04:00
Shaun Walker
62879c3e52 Merge pull request #5162 from sbwalker/dev
upgrade to .NET 9.0.3
2025-03-11 14:36:14 -04:00
sbwalker
45610f8dd7 upgrade to .NET 9.0.3 2025-03-11 14:35:59 -04:00
Shaun Walker
18102cbd78 Merge pull request #5160 from sbwalker/dev
sort endpoints by route
2025-03-11 13:11:34 -04:00
sbwalker
262d6a1529 sort endpoints by route 2025-03-11 13:11:19 -04:00
Shaun Walker
1124ddaf90 Merge pull request #5157 from zyhfish/task/fix-5156
Fix #5156: update the bind event to oninput.
2025-03-11 11:51:38 -04:00
Shaun Walker
981add3872 Merge pull request #5158 from sbwalker/dev
rename Cache service to OutputCache
2025-03-11 11:48:58 -04:00
sbwalker
8d4b30140e rename Cache service to OutputCache 2025-03-11 11:48:43 -04:00
Ben
b9c59137a8 Fix #5156: update the bind event to oninput. 2025-03-11 22:58:06 +08:00
Shaun Walker
0b1c7e06ca Update README.md 2025-03-10 10:56:41 -04:00
Shaun Walker
fcaf80cba6 Update README.md 2025-03-10 10:56:11 -04:00
Shaun Walker
6358b9eabb Merge pull request #5155 from sbwalker/dev
added Logout Everywhere option to User Settings
2025-03-10 10:53:25 -04:00
sbwalker
70a3fab1ff added Logout Everywhere option to User Settings 2025-03-10 10:53:05 -04:00
Shaun Walker
bdf86ace86 Merge pull request #5152 from sbwalker/dev
upgrade to ImageSharp 3.1.7 due to security vulnerability
2025-03-07 14:17:02 -05:00
sbwalker
d57132d1e4 upgrade to ImageSharp 3.1.7 due to security vulnerability 2025-03-07 14:16:47 -05:00
Shaun Walker
a6e87abf99 Merge pull request #5151 from sbwalker/dev
allow site settings to be overidden at host level
2025-03-07 14:15:31 -05:00
sbwalker
f1771610fe allow site settings to be overidden at host level 2025-03-07 14:15:16 -05:00
Shaun Walker
a88ea9780f Update README.md 2025-03-06 15:45:30 -05:00
Shaun Walker
bca0866d72 Update README.md 2025-03-06 15:43:59 -05:00
Shaun Walker
cebed93abf Update README.md 2025-03-06 15:42:48 -05:00
Shaun Walker
ee2b2e3569 Update README.md 2025-03-06 15:40:07 -05:00
Shaun Walker
cb8e9ee244 Update README.md 2025-03-06 15:38:18 -05:00
Shaun Walker
486184b16c Update README.md 2025-03-06 15:36:28 -05:00
Shaun Walker
9f9bd1988f Merge pull request #5149 from sbwalker/dev
update based on changes suggested by @adefwebserver
2025-03-06 15:25:37 -05:00
sbwalker
ba1bfd1bc0 update based on changes suggested by @adefwebserver 2025-03-06 15:25:25 -05:00
Shaun Walker
e12926e971 Merge pull request #5148 from sbwalker/dev
allow page and module settings to be included in site templates, improve terms and privacy default content, add Settings for HtmlText module
2025-03-06 14:46:38 -05:00
sbwalker
5b4db0de3b allow page and module settings to be included in site templates, improve terms and privacy default content, add Settings for HtmlText module 2025-03-06 14:46:17 -05:00
Shaun Walker
70ff55faa6 Merge pull request #5147 from sbwalker/dev
modify terminology
2025-03-06 09:43:55 -05:00
sbwalker
f2bd47d8bc modify terminology 2025-03-06 09:43:40 -05:00
Shaun Walker
e2b9c9e98e Merge pull request #5146 from sbwalker/dev
prepare for 6.1.1
2025-03-05 15:02:39 -05:00
sbwalker
b0791a594f prepare for 6.1.1 2025-03-05 15:02:12 -05:00
Shaun Walker
ea5eaa6ed2 Merge pull request #5145 from sbwalker/dev
update to .NET 9.0.2
2025-03-05 14:55:00 -05:00
sbwalker
ec3fd1d585 update to .NET 9.0.2 2025-03-05 14:54:46 -05:00
Shaun Walker
d76de22977 Merge pull request #5144 from sbwalker/dev
modify localization text
2025-03-05 10:45:17 -05:00
sbwalker
c0e3483cc7 modify localization text 2025-03-05 10:44:34 -05:00
Shaun Walker
0994cdf3b6 Merge pull request #5141 from sbwalker/dev
sync interop.js changes with .NET MAUI
2025-03-04 16:25:24 -05:00
sbwalker
a76fd82262 sync interop.js changes with .NET MAUI 2025-03-04 16:25:10 -05:00
Shaun Walker
2f919c7d69 Merge pull request #5140 from sbwalker/dev
fix regression issue with Search component
2025-03-04 15:45:16 -05:00
sbwalker
f12592731b fix regression issue with Search component 2025-03-04 15:45:02 -05:00
Shaun Walker
4a20e1a25d Merge pull request #5138 from zyhfish/task/improve-middle-screen-view
improve the styles in middle screen size.
2025-03-04 15:42:37 -05:00
Shaun Walker
cc7111c3ff Merge pull request #5139 from sbwalker/dev
change module title for Terms
2025-03-04 15:40:58 -05:00
sbwalker
81972aed62 change module title for Terms 2025-03-04 15:40:44 -05:00
Ben
5e2092c6d4 improve the styles in middle screen size. 2025-03-04 23:31:21 +08:00
Shaun Walker
d136f8ac91 Merge pull request #5137 from sbwalker/dev
add nonce support
2025-03-03 16:49:41 -05:00
sbwalker
5b23917940 add nonce support 2025-03-03 16:49:28 -05:00
Shaun Walker
2cda0a3798 Merge pull request #5136 from sbwalker/dev
modify cookie consent text
2025-03-03 15:37:46 -05:00
sbwalker
f315ad1ce9 modify cookie consent text 2025-03-03 15:37:31 -05:00
Shaun Walker
49f1c273c2 Merge pull request #5134 from sbwalker/dev
add terms to upgrademanager
2025-03-03 13:36:47 -05:00
sbwalker
8518476c87 add terms to upgrademanager 2025-03-03 13:36:32 -05:00
Shaun Walker
a34ed756db Merge pull request #5132 from mdmontesinos/sitemap-cache
resolves #4899: output cache for sitemap
2025-03-03 13:22:46 -05:00
Shaun Walker
a48232c4e3 Merge pull request #5133 from sbwalker/dev
add default privacy and terms
2025-03-03 13:22:33 -05:00
sbwalker
ac65e38390 add default privacy and terms 2025-03-03 13:22:17 -05:00
David Montesinos
eab3a753f5 resolves #4899: output cache for sitemap 2025-03-03 17:54:33 +01:00
Shaun Walker
9e5922e121 Merge pull request #5130 from zyhfish/task/fix-4936
Fix #4936: set the allow cookie value when refresh state.
2025-03-03 07:57:42 -05:00
Ben
bf57b23776 update the page state after policy changed. 2025-03-01 15:05:23 +08:00
Ben
8f4a20fd46 Fix #4936: set the allow cookie value when refresh state. 2025-03-01 14:16:42 +08:00
Shaun Walker
b3716da5ac Merge pull request #5128 from zyhfish/task/fix-4936-new
move the styles to app.css.
2025-02-28 13:36:58 -05:00
Shaun Walker
2c129fd800 Merge pull request #5129 from sbwalker/dev
localization text change
2025-02-28 13:36:49 -05:00
sbwalker
6fb18e7a25 localization text change 2025-02-28 13:36:34 -05:00
Ben
38d28d6944 move the styles to app.css. 2025-02-28 23:53:53 +08:00
Shaun Walker
a187e1a7a2 Merge pull request #5127 from sbwalker/dev
fix RESX issue
2025-02-28 10:52:18 -05:00
sbwalker
7d7a19c7c2 fix RESX issue 2025-02-28 10:52:06 -05:00
Shaun Walker
6a2ae2153a Merge pull request #5119 from zyhfish/task/fix-4936
update the cookie consent control.
2025-02-28 10:48:21 -05:00
Shaun Walker
f50ba1a91e Merge branch 'dev' into task/fix-4936 2025-02-28 10:47:24 -05:00
Shaun Walker
b09575dbd6 Merge pull request #5126 from sbwalker/dev
provide option to assign a theme to a site
2025-02-28 10:45:40 -05:00
sbwalker
c52ee3d91d provide option to assign a theme to a site 2025-02-28 10:45:25 -05:00
Ben
1ced5c0425 update the cookie consent control. 2025-02-28 23:32:17 +08:00
Shaun Walker
e399a5c9b1 Merge pull request #5124 from sbwalker/dev
add missing maxlength attributes
2025-02-27 10:51:37 -05:00
sbwalker
08dff5fb67 add missing maxlength attributes 2025-02-27 10:51:22 -05:00
Shaun Walker
912760f2a7 Update SECURITY.md 2025-02-26 15:29:49 -05:00
Shaun Walker
4b62fdbf93 Update SECURITY.md 2025-02-26 15:27:33 -05:00
Shaun Walker
df593d43a7 Update SECURITY.md 2025-02-26 15:25:25 -05:00
Shaun Walker
89b1fba771 Merge pull request #5123 from sbwalker/dev
remove package validation logic
2025-02-26 12:54:06 -05:00
sbwalker
5505c91ae0 remove package validation logic 2025-02-26 12:53:53 -05:00
Shaun Walker
cc720ff399 Merge pull request #5122 from sbwalker/dev
remove unnecessary log message
2025-02-26 12:12:14 -05:00
sbwalker
29f07f6c56 remove unnecessary log message 2025-02-26 12:11:56 -05:00
Shaun Walker
a69e197a1f Merge pull request #5121 from zyhfish/task/fix-5116
Fix #5116: parse the value as UTC time.
2025-02-26 07:45:55 -05:00
Ben
6dddd8eff8 only allow essential cookies when cookie consent not granted. 2025-02-26 19:41:58 +08:00
Ben
51aada8922 Fix #5116: parse the value as UTC time. 2025-02-26 18:25:24 +08:00
Ben
b47bf40e8f update the cookie consent control. 2025-02-25 11:36:47 +08:00
Shaun Walker
48151bf365 Merge pull request #5118 from sbwalker/dev
remove IJSRuntime reference as it was causing a compilation warning
2025-02-24 16:15:51 -05:00
sbwalker
659950996d remove IJSRuntime reference as it was causing a compilation warning 2025-02-24 16:15:35 -05:00
Shaun Walker
6e656a4d0a Merge pull request #5114 from zyhfish/task/fix-4936
Fix #4936: add the cookie consent theme control.
2025-02-24 16:08:22 -05:00
Ben
bf308dd13d enable child component of cookie consent control. 2025-02-24 22:32:19 +08:00
Ben
982f3b1943 Fix #4936: add the cookie consent theme control. 2025-02-22 09:49:33 +08:00
Shaun Walker
7a4ea8cf1b Merge pull request #5094 from zyhfish/task/set-fa-ir-culture
Fix #5054: resolve the issue in fa-IR language.
2025-02-19 07:36:16 -05:00
Shaun Walker
7c0482a87c Merge pull request #5111 from sbwalker/dev
remove warning message related to no jobs being registered
2025-02-18 11:50:57 -05:00
sbwalker
101ededd89 remove warning message related to no jobs being registered 2025-02-18 11:50:36 -05:00
Shaun Walker
a8cbc0040e Merge pull request #5108 from zyhfish/task/fix-5103
Fix #5103: return a copy of the assembly list.
2025-02-18 11:40:30 -05:00
Shaun Walker
ed91bb445b Merge pull request #5110 from sbwalker/dev
improve HostedServiceBase so that scheduled jobs can be registered during installation
2025-02-18 11:36:00 -05:00
sbwalker
f158a222f4 improve HostedServiceBase so that scheduled jobs can be registered during installation 2025-02-18 11:35:38 -05:00
Shaun Walker
46bcad1fca Merge pull request #5109 from sbwalker/dev
clean up scheduled jobs which have been uninstalled
2025-02-18 09:12:48 -05:00
sbwalker
5e147afb9f clean up scheduled jobs which have been uninstalled 2025-02-18 09:12:26 -05:00
Ben
b061d4593f Fix #5103: return a copy of the assembly list. 2025-02-18 22:02:25 +08:00
Shaun Walker
3fa520b4ef Merge pull request #5107 from sbwalker/dev
make purge job output more readable
2025-02-18 08:53:38 -05:00
sbwalker
2df05b4afd make purge job output more readable 2025-02-18 08:53:23 -05:00
Shaun Walker
e0569a6748 Merge pull request #5104 from sbwalker/dev
fix visitor purge logic
2025-02-17 13:22:11 -05:00
sbwalker
2e6ab398d9 fix visitor purge logic 2025-02-17 13:21:58 -05:00
Ben
94b03d2a6b update settings for all RTL languages. 2025-02-16 10:25:43 +08:00
Shaun Walker
f84fe30bb6 Merge pull request #5097 from sbwalker/dev
synchronize BlazorScriptReload changes
2025-02-14 09:17:58 -05:00
sbwalker
049ddef531 synchronize BlazorScriptReload changes 2025-02-14 09:17:44 -05:00
Shaun Walker
a1a214c742 Merge pull request #5096 from sbwalker/dev
add another constructor for Script class
2025-02-14 09:09:14 -05:00
sbwalker
c40a483ffa add another constructor for Script class 2025-02-14 09:09:00 -05:00
Ben
aff99acfae Fix #5054: resolve the issue in fa-IR language. 2025-02-12 20:18:10 +08:00
Shaun Walker
628129c08d Update README.md 2025-02-11 12:00:41 -05:00
Shaun Walker
679d34dfdf Merge pull request #5093 from oqtane/master
6.1.0 Release
2025-02-11 11:49:29 -05:00
Shaun Walker
b2f65903ae Merge pull request #5092 from oqtane/dev
6.1.0 Release
2025-02-11 11:49:06 -05:00
Shaun Walker
2daefe0382 Merge pull request #5091 from tvatavuk/patch-1
Minor fix in ThemeController.cs
2025-02-11 11:41:52 -05:00
Tonći Vatavuk
1214a11704 Minor fix in ThemeController.cs
update `SharedReference` to use "Oqtane.Shared" for PackageReference code
2025-02-11 14:35:13 +01:00
Shaun Walker
e55e0118c2 Merge pull request #5090 from sbwalker/dev
fix #5089 - remove upgrade cleanup logic as .NET 9.0.1 moves assemblies back to /bin folder
2025-02-10 16:53:42 -05:00
sbwalker
a1ac81e907 fix #5089 - remove upgrade cleanup logic as .NET 9.0.1 moves assemblies back to /bin folder 2025-02-10 16:53:22 -05:00
Shaun Walker
14ad68bf69 Merge pull request #5088 from sbwalker/dev
modify RemoveAssemblies method so that it only runs once - not for every tenant
2025-02-10 16:27:24 -05:00
sbwalker
e3118c6e99 modify RemoveAssemblies method so that it only runs once - not for every tenant 2025-02-10 16:27:05 -05:00
Shaun Walker
b41aeab8f8 Merge pull request #5087 from sbwalker/dev
update Provider property to Pomelo
2025-02-10 10:47:07 -05:00
sbwalker
1a738b358e update Provider property to Pomelo 2025-02-10 10:46:44 -05:00
Shaun Walker
f4b1e8035b Merge pull request #5086 from sbwalker/dev
improve notification add and update methods
2025-02-10 09:50:35 -05:00
sbwalker
324e985247 improve notification add and update methods 2025-02-10 09:50:21 -05:00
Shaun Walker
60faacd7d0 Merge pull request #5085 from sbwalker/dev
fix comment
2025-02-10 08:21:13 -05:00
sbwalker
d4a4d7c346 fix comment 2025-02-10 08:20:58 -05:00
Shaun Walker
189f8f1d27 Merge pull request #5082 from sbwalker/dev
enhance purge job to trim broken urls based on retention policy
2025-02-09 13:02:21 -05:00
sbwalker
ed353461da enhance purge job to trim broken urls based on retention policy 2025-02-09 13:02:07 -05:00
Shaun Walker
e9330d6c62 Merge pull request #5080 from zyhfish/task/fix-5079
Fix #5079: Retrieve all Url Mapping records
2025-02-09 12:35:28 -05:00
Shaun Walker
f53e7cc3f6 Merge pull request #5081 from sbwalker/dev
fix #5072 - administrators should be allowed to send system notifications
2025-02-09 12:34:38 -05:00
sbwalker
4f4258d532 fix #5072 - administrators should be allowed to send system notifications 2025-02-09 12:34:17 -05:00
Ben
c80910f355 Fix #5079: remove the records limit. 2025-02-08 11:51:38 +08:00
Shaun Walker
12470ab178 Merge pull request #5075 from mdmontesinos/dev
fix #5074: generate cancellation token for file upload
2025-02-07 07:53:16 -05:00
Shaun Walker
704e091e9b Merge pull request #5076 from sbwalker/dev
synchronize interop script changes with .NET MAUI
2025-02-07 07:52:58 -05:00
sbwalker
f30f1e5c1f synchronize interop script changes with .NET MAUI 2025-02-07 07:52:43 -05:00
David Montesinos
0741ce2197 fix #5074: generate cancellation token for file upload 2025-02-07 09:11:52 +01:00
Shaun Walker
fc81bae9b7 Update README.md 2025-02-06 15:16:50 -05:00
Shaun Walker
3fa68e4f96 Merge pull request #5071 from sbwalker/dev
moved file setting to File Management and added Max Chunk Size
2025-02-06 15:10:29 -05:00
sbwalker
05a767c7be moved file setting to File Management and added Max Chunk Size 2025-02-06 15:10:14 -05:00
Shaun Walker
8c1e8f6377 Merge pull request #5070 from sbwalker/dev
fix #5067 - add support for Guid data types
2025-02-06 14:17:06 -05:00
sbwalker
0fbae8d7da fix #5067 - add support for Guid data types 2025-02-06 14:16:53 -05:00
Shaun Walker
cec4b339f5 Merge pull request #5069 from mdmontesinos/dev-test
fix #5058: ensure sequential file and chunk uploads to avoid overload
2025-02-06 13:56:35 -05:00
David Montesinos
1a7656d8ee fix #5058: ensure sequential file and chunk uploads to avoid overload 2025-02-06 19:21:51 +01:00
Shaun Walker
e173815810 Merge pull request #5068 from sbwalker/dev
fix LogLevel for file upload error
2025-02-06 12:21:51 -05:00
sbwalker
620c768e05 fix LogLevel for file upload error 2025-02-06 12:21:34 -05:00
Shaun Walker
7740679077 Merge pull request #5066 from sbwalker/dev
fix #5061 - configure Page Management for personalizable pages
2025-02-06 11:16:46 -05:00
sbwalker
1ebc8ebff3 fix #5061 - configure Page Management for personalizable pages 2025-02-06 11:16:30 -05:00
Shaun Walker
fa4fac70d5 Merge pull request #5065 from sbwalker/dev
improve file upload validation and error handling on server
2025-02-06 08:20:13 -05:00
sbwalker
8c83a18f93 improve file upload validation and error handling on server 2025-02-06 08:19:57 -05:00
Shaun Walker
a151ecfda0 Merge pull request #5064 from sbwalker/dev
modified file upload error message to reflect new behavior
2025-02-05 19:10:10 -05:00
sbwalker
dec0c0649c modified file upload error message to reflect new behavior 2025-02-05 19:09:55 -05:00
Shaun Walker
a356f893ac Merge pull request #5063 from sbwalker/dev
remove uploadFile() method as it is not used
2025-02-05 17:08:56 -05:00
sbwalker
e2af4f74c3 remove uploadFile() method as it is not used 2025-02-05 17:08:32 -05:00
Shaun Walker
99022b76e5 Merge pull request #5062 from sbwalker/dev
file upload improvements
2025-02-05 16:48:59 -05:00
sbwalker
9dd6dc7523 file upload improvements 2025-02-05 16:48:34 -05:00
Shaun Walker
6f588200d7 Merge pull request #5057 from sbwalker/dev
fix #5044 - improve file part removal logic
2025-02-03 11:00:37 -05:00
sbwalker
f3dbeae28e fix #5044 - improve file part removal logic 2025-02-03 11:00:22 -05:00
Shaun Walker
9f70361298 Merge pull request #5056 from sbwalker/dev
add additional Script class constructors
2025-02-03 10:35:32 -05:00
sbwalker
534353ce13 add additional Script class constructors 2025-02-03 10:35:17 -05:00
Shaun Walker
3f391a7354 Merge pull request #5052 from sbwalker/dev
modify button spacing
2025-01-31 14:51:06 -05:00
sbwalker
0dd0752710 modify button spacing 2025-01-31 14:50:54 -05:00
Shaun Walker
710fae4b0e Merge pull request #5051 from sbwalker/dev
add user impersonation
2025-01-31 11:14:28 -05:00
sbwalker
de6c57a7ee add user impersonation 2025-01-31 11:14:13 -05:00
Shaun Walker
7eee1fcd6a Merge pull request #5050 from sbwalker/dev
make Kestrel the default profile in launchjSettings.json
2025-01-31 09:18:59 -05:00
sbwalker
1fd2aedf96 make Kestrel the default profile in launchjSettings.json 2025-01-31 09:18:44 -05:00
Shaun Walker
ffdd7c063b Merge pull request #5049 from sbwalker/dev
added a ScriptsLoaded property in ModuleBase and ThemeBase for flow control in Interactive rendering scenarios
2025-01-31 08:42:56 -05:00
sbwalker
a87af264eb added a ScriptsLoaded property in ModuleBase and ThemeBase for flow control in Interactive rendering scenarios 2025-01-31 08:42:36 -05:00
Shaun Walker
3640cd2fdd Merge pull request #5046 from sbwalker/dev
fix upgrade issue which can occur in development environments
2025-01-30 08:40:08 -05:00
sbwalker
f7cf25c4bb fix upgrade issue which can occur in development environments 2025-01-30 08:39:49 -05:00
Shaun Walker
77dbd0d4c7 Merge pull request #5045 from sbwalker/dev
update version to 6.1.0
2025-01-30 08:08:34 -05:00
sbwalker
5a77c83e68 update version to 6.1.0 2025-01-30 08:08:16 -05:00
Shaun Walker
0a6763e08c Merge pull request #5043 from sbwalker/dev
change ResourceLoadBehavior Never to None
2025-01-29 19:05:20 -05:00
sbwalker
b5aa206670 change ResourceLoadBehavior Never to None 2025-01-29 19:05:05 -05:00
Shaun Walker
dbb4d9b64b Merge pull request #5042 from sbwalker/dev
fix logic to retrieve access token
2025-01-29 16:03:11 -05:00
sbwalker
6775edfd66 fix logic to retrieve access token 2025-01-29 16:02:55 -05:00
Shaun Walker
b06750ed65 Merge pull request #5040 from sbwalker/dev
remove method which was relocated to PageRepository
2025-01-29 13:12:59 -05:00
sbwalker
57879c1891 remove method which was relocated to PageRepository 2025-01-29 13:12:46 -05:00
Shaun Walker
65b55a76f2 Merge pull request #5039 from sbwalker/dev
improve asset caching help text
2025-01-29 12:40:02 -05:00
sbwalker
8562a68306 improve asset caching help text 2025-01-29 12:39:47 -05:00
Shaun Walker
160da46b5a Merge pull request #5038 from sbwalker/dev
remove Environment.IsDevelopment logic
2025-01-29 12:27:57 -05:00
sbwalker
ae5f70a739 remove Environment.IsDevelopment logic 2025-01-29 12:27:42 -05:00
Shaun Walker
4456e57466 Merge pull request #5036 from sbwalker/dev
use fingerprint term consistently
2025-01-29 10:42:34 -05:00
sbwalker
24cd090c61 use fingerprint term consistently 2025-01-29 10:42:19 -05:00
Shaun Walker
4f849f5d5f Merge pull request #5035 from sbwalker/dev
performance improvement when loading files within a folder
2025-01-29 10:23:11 -05:00
sbwalker
db2e86e84c performance improvement when loading files within a folder 2025-01-29 10:22:56 -05:00
Shaun Walker
14748ce2b3 Merge pull request #5034 from sbwalker/dev
use Configuration service as it already exists
2025-01-29 08:28:08 -05:00
sbwalker
527509732c use Configuration service as it already exists 2025-01-29 08:22:21 -05:00
Shaun Walker
aa9214477c Merge pull request #5033 from sbwalker/dev
fix #5018 - redirect file download to login page
2025-01-28 16:31:03 -05:00
sbwalker
db24ed8b55 fix #5018 - redirect file download to login page 2025-01-28 16:30:49 -05:00
Shaun Walker
349d1849d9 Merge pull request #5032 from sbwalker/dev
use deterministic hash in file server image generation
2025-01-28 15:55:56 -05:00
sbwalker
188be2fa8c use deterministic hash in file server image generation 2025-01-28 15:55:40 -05:00
Shaun Walker
5c4d7df734 Merge pull request #5031 from sbwalker/dev
remove Oqtane.Server.staticwebassets.endpoints.json from release packages
2025-01-28 14:39:48 -05:00
sbwalker
37de18c670 remove Oqtane.Server.staticwebassets.endpoints.json from release packages 2025-01-28 14:39:30 -05:00
Shaun Walker
0001e3844b Merge pull request #5030 from sbwalker/dev
provides options to control caching for static assets
2025-01-28 14:30:13 -05:00
sbwalker
65f171f701 provides options to control caching for static assets 2025-01-28 14:29:58 -05:00
Shaun Walker
c4308c239c Merge pull request #5007 from RahulKaushik007/fix-static-file-caching
Fixes #5005: Add Browser Caching for Static Assets
2025-01-28 13:21:29 -05:00
Shaun Walker
2b6af3cb37 Merge pull request #5029 from sbwalker/dev
fix localization text
2025-01-28 13:18:32 -05:00
sbwalker
c5a16fbbc1 fix localization text 2025-01-28 13:18:18 -05:00
Shaun Walker
1db83f509b Merge pull request #5028 from sbwalker/dev
add caching support for folders
2025-01-28 12:47:37 -05:00
sbwalker
2a06304a2c add caching support for folders 2025-01-28 12:47:23 -05:00
Shaun Walker
7bbe684135 Merge pull request #5027 from sbwalker/dev
improve terminology consistency
2025-01-28 08:56:19 -05:00
sbwalker
a996a88fc4 improve terminology consistency 2025-01-28 08:56:05 -05:00
Shaun Walker
8cf9e7db51 Merge pull request #5026 from sbwalker/dev
add Fingerprint property to ModuleBase and ThemeBase
2025-01-28 08:44:01 -05:00
sbwalker
ed981c67b7 add Fingerprint property to ModuleBase and ThemeBase 2025-01-28 08:43:48 -05:00
Shaun Walker
6a77a0a5b9 Merge pull request #5025 from sbwalker/dev
improve terminology
2025-01-28 08:34:31 -05:00
sbwalker
bfb4b4431b improve terminology 2025-01-28 08:34:15 -05:00
Shaun Walker
3de44c0335 Merge pull request #5024 from sbwalker/dev
add ThemeState property to ThemeBase
2025-01-28 08:27:25 -05:00
sbwalker
37afd1aec9 add ThemeState property to ThemeBase 2025-01-28 08:27:10 -05:00
Shaun Walker
b2ac561673 Merge pull request #5021 from thabaum/update-package-dependencies-9.0.1
Fixes #5020: Updates package dependencies 9.0.1 (Latest)
2025-01-27 16:44:33 -05:00
Shaun Walker
c9bf7d9138 Merge pull request #5022 from sbwalker/dev
fix #5005 - adds versioning (ie. fingerprinting) for static assets - core, modules, and themes.
2025-01-27 16:35:07 -05:00
sbwalker
153a689bdb fix #5005 - adds versioning (ie. fingerprinting) for static assets - core, modules, and themes. 2025-01-27 16:34:47 -05:00
Cody
26b88f1a22 Update Package Dependencies to 9.0.1 2025-01-27 05:13:31 -08:00
Cody
c66a5d028f Update Package Dependencies to 9.0.1 2025-01-27 05:13:01 -08:00
Cody
8441c95a5c Update Package Dependencies to 9.0.1 2025-01-27 05:11:49 -08:00
Cody
e0e32b0199 Update Package Dependencies to 9.0.1 and 9.0.30 2025-01-27 05:09:19 -08:00
Cody
2bb76564e9 Update Package Dependencies to 9.0.1 2025-01-27 05:06:46 -08:00
Cody
86ec25d4de Update Package Dependencies to 9.0.1 2025-01-27 05:05:42 -08:00
Cody
ed9929963c Update Package Dependencies to 9.0.1 2025-01-27 05:04:34 -08:00
Cody
36f50118ac Update Package Dependencies to 9.0.1 2025-01-27 05:03:46 -08:00
Cody
72ddf27504 Update Package Dependency to 9.2.0 2025-01-27 05:03:03 -08:00
Cody
9bd36931ff Update Package Dependencies to 9.0.1 2025-01-27 05:02:10 -08:00
Cody
056ef7a3d5 Update Package Dependencies to 9.0.1 2025-01-27 05:00:08 -08:00
Shaun Walker
e483945d05 Merge pull request #5017 from sbwalker/dev
fix #5014 - page content scripts not loading on initial page request in Interactive rendering
2025-01-24 14:29:42 -05:00
sbwalker
7a9c637e03 fix #5014 - page content scripts not loading on initial page request in Interactive rendering 2025-01-24 14:29:23 -05:00
Shaun Walker
09ce543ea6 Merge pull request #5013 from sbwalker/dev
allow packages to be managed across installations
2025-01-23 09:08:16 -05:00
sbwalker
0ef24ebc3f allow packages to be managed across installations 2025-01-23 09:08:02 -05:00
Shaun Walker
a4419d3af6 Merge pull request #5011 from sbwalker/dev
remove GetButtonSize method
2025-01-22 07:43:38 -05:00
sbwalker
935983c02a remove GetButtonSize method 2025-01-22 07:43:23 -05:00
Shaun Walker
bd54ce5017 Merge pull request #4998 from leigh-pointer/ActionDialogSize
Update ActionDialog Add method to ensure consistent button sizing
2025-01-22 07:42:04 -05:00
Leigh Pointer
af6ed78b8e Update ActionDialog.razor 2025-01-22 07:57:52 +01:00
Leigh Pointer
f72438996d Merge remote-tracking branch 'upstream/dev' into ActionDialogSize 2025-01-22 07:36:01 +01:00
Shaun Walker
9db2a55a5a Merge pull request #5010 from sbwalker/dev
fix #4964 - use bearer token if it already exists
2025-01-21 16:55:19 -05:00
sbwalker
950d90badb fix #4964 - use bearer token if it already exists 2025-01-21 16:55:02 -05:00
Shaun Walker
1864d180af Merge pull request #5003 from sdi2121/patch-1
Update Oqtane.Server.csproj - MySQL deploy to Azure error
2025-01-21 15:58:44 -05:00
Shaun Walker
0e82e98382 Merge pull request #5006 from mdmontesinos/patch-1
FIX: File server MimeType not updated after image conversion
2025-01-21 15:58:33 -05:00
Shaun Walker
46023d35dc Merge pull request #5009 from sbwalker/dev
fix #4976 - manage hierarchical path updates and page deletion
2025-01-21 15:58:08 -05:00
sbwalker
90d2e0a40b fix #4976 - manage hierarchical path updates and page deletion 2025-01-21 15:57:48 -05:00
Shaun Walker
5f884e0796 Merge pull request #5008 from sbwalker/dev
fix #4965 - improve user/site management
2025-01-21 12:21:50 -05:00
sbwalker
16477052e2 fix #4965 - improve user/site management 2025-01-21 12:21:27 -05:00
RahulKaushik007
66a05603f7 Fix static file caching headers 2025-01-21 17:42:08 +05:30
RahulKaushik007
fe2a883386 Fix static file caching headers 2025-01-21 17:26:47 +05:30
David Montesinos
ca7fdaa125 FIX: File server MimeType not updated after image conversion 2025-01-20 12:17:22 +01:00
sdi2121
1283ec2008 Update Oqtane.Server.csproj
Fixes Azure manual deployment build from local code build. May need an additional fix in MySQL library (Line 24 - MySQLDatabase.cs)
2025-01-18 13:53:04 -05:00
Shaun Walker
d1f78f9048 Update LICENSE 2025-01-17 12:57:32 -05:00
Shaun Walker
45f43bfade Merge pull request #5002 from sbwalker/dev
update copyright year
2025-01-17 12:57:14 -05:00
sbwalker
4793ab4bc9 update copyright year 2025-01-17 12:56:59 -05:00
Shaun Walker
88b174dea8 Merge pull request #5001 from sbwalker/dev
remove unused method
2025-01-17 12:50:42 -05:00
sbwalker
06ca382bd7 remove unused method 2025-01-17 12:50:26 -05:00
Shaun Walker
b09175a8db Merge pull request #5000 from sbwalker/dev
allow entry of name during installation
2025-01-17 11:14:49 -05:00
sbwalker
677f68b08d allow entry of name during installation 2025-01-17 11:14:35 -05:00
Shaun Walker
8058b8dba4 Merge pull request #4999 from sbwalker/dev
improve error messages
2025-01-17 07:54:49 -05:00
sbwalker
4bc26f13c1 improve error messages 2025-01-17 07:54:34 -05:00
Leigh Pointer
e6cf77e724 Update ActionDialog Add method to ensure consistent button sizing
This PR introduces a new private method GetButtonSize() to enhance the consistency of button sizing within our UI. The method specifically checks for the presence of the "btn-sm" class in the Action Button's class list and applies the same sizing to the Cancel Button if found.
2025-01-17 13:34:16 +01:00
Shaun Walker
f8737c112e Merge pull request #4997 from sbwalker/dev
reload the script if data-reload is "always" or if the script has not been loaded previously and data-reload is "once" or "true"
2025-01-16 15:06:36 -05:00
sbwalker
74b72ed9d4 reload the script if data-reload is "always" or if the script has not been loaded previously and data-reload is "once" or "true" 2025-01-16 15:06:15 -05:00
Shaun Walker
4950391201 Merge pull request #4996 from sbwalker/dev
allow data-reload to support true or always
2025-01-16 14:22:06 -05:00
sbwalker
64a38d6e45 allow data-reload to support true or always 2025-01-16 14:21:52 -05:00
Shaun Walker
e2d8ee53f8 Merge pull request #4995 from sbwalker/dev
script reload improvements
2025-01-16 14:06:28 -05:00
sbwalker
0204ff8dd5 script reload improvements 2025-01-16 14:06:13 -05:00
Shaun Walker
4630ee6e93 Merge pull request #4992 from beolafsen/dev
Trim ModuleOwner and ModuleName before create
2025-01-16 12:29:00 -05:00
Shaun Walker
c4f2abf143 Merge pull request #4994 from sbwalker/dev
fix #4986 - allow Resources which have Reload specified to be used in Interactive rendering
2025-01-16 12:26:30 -05:00
sbwalker
e7444a0194 fix #4986 - allow Resources which have Reload specified to be used in Interactive rendering 2025-01-16 12:26:10 -05:00
Shaun Walker
ffed7305ed Merge pull request #4993 from sbwalker/dev
fix #4984 - path mapping for personalized pages
2025-01-16 09:25:43 -05:00
sbwalker
334054bcd4 fix #4984 - path mapping for personalized pages 2025-01-16 09:25:27 -05:00
beolafsen
5bb98eb5b2 Trim ModuleOwner and ModuleName before create 2025-01-16 09:32:18 +01:00
Shaun Walker
e842bd882a Merge pull request #4991 from sbwalker/dev
fix #4984 - redirect not working for personalized pages
2025-01-15 11:57:00 -05:00
sbwalker
74bfb46f73 fix #4984 - redirect not working for personalized pages 2025-01-15 11:56:44 -05:00
Shaun Walker
cd45bf4b70 Merge pull request #4989 from sbwalker/dev
fix #4984 - ensure personalized page path does not contain illegal characters
2025-01-14 15:43:00 -05:00
sbwalker
51600bbcb0 fix #4984 - ensure personalized page path does not contain illegal characters 2025-01-14 15:42:40 -05:00
Shaun Walker
8811a9bcaa Merge pull request #4988 from sbwalker/dev
introduce RemoveAssemblies() method in UpgradeManager
2025-01-14 08:43:38 -05:00
sbwalker
4521f8a774 introduce RemoveAssemblies() method in UpgradeManager 2025-01-14 08:43:23 -05:00
Shaun Walker
5b427783f8 Merge pull request #4987 from zyhfish/task/fix-4954
Fix #4954: use Pomelo.EntityFrameworkCore.MySql package.
2025-01-14 08:34:34 -05:00
Ben
9508983b15 Fix #4954: use Pomelo.EntityFrameworkCore.MySql package. 2025-01-14 19:58:56 +08:00
Shaun Walker
fd09912cd7 Merge pull request #4978 from beolafsen/dev
Issue #4977
2025-01-13 16:00:06 -05:00
Shaun Walker
01cc8584b6 Merge pull request #4968 from leigh-pointer/unused
Removed unused Using statements from the SiteTemplates
2025-01-13 15:56:39 -05:00
Shaun Walker
c0b104e7c8 Merge pull request #4962 from thabaum/prepare-6.0.2-update-dependencies
Fixes #4961 - Updates Oqtane version to 6.0.2 and update related project dependencies to latest.
2025-01-13 15:55:13 -05:00
Shaun Walker
9a82021a82 Merge pull request #4983 from sbwalker/dev
include option for external login to save tokens
2025-01-13 15:14:27 -05:00
sbwalker
1fb54a0b0f include option for external login to save tokens 2025-01-13 15:14:13 -05:00
Shaun Walker
aa5ea61638 Merge pull request #4982 from sbwalker/dev
improve filtering logic in UserRole API
2025-01-13 14:42:36 -05:00
sbwalker
a59ec0258b improve filtering logic in UserRole API 2025-01-13 14:42:19 -05:00
Shaun Walker
b403f5cf71 Merge pull request #4980 from sbwalker/dev
fix comment spelling
2025-01-13 07:50:21 -05:00
sbwalker
0ac6a62b86 fix comment spelling 2025-01-13 07:50:05 -05:00
Shaun Walker
ed3743d3b6 Merge pull request #4979 from sbwalker/dev
fix #4969 - improve feedback and flow when connection string points to an invalid database
2025-01-13 07:48:50 -05:00
sbwalker
3468cba000 fix #4969 - improve feedback and flow when connection string points to an invalid database 2025-01-13 07:48:30 -05:00
beolafsen
5a4cdc5354 Issue #4977 2025-01-13 07:31:35 +01:00
Leigh Pointer
af4e19a57e Removed unused Using statements from the SiteTemplates 2025-01-07 04:14:31 +01:00
Cody
26bb743679 Prepare 6.0.2 2024-12-31 10:37:27 -08:00
Cody
96cc726e22 Prepare 6.0.2 2024-12-31 10:35:00 -08:00
Cody
f4b00b01d0 Prepare 6.0.2 2024-12-31 10:34:21 -08:00
Cody
127b2ca86d Prepare 6.0.2 2024-12-31 10:32:09 -08:00
Cody
4b8b93e1b8 Prepare 6.0.2 2024-12-31 10:31:47 -08:00
Cody
3aea412fe9 Prepare 6.0.2 2024-12-31 10:31:23 -08:00
Cody
2aef96ad4f Prepare 6.0.2 2024-12-31 10:29:52 -08:00
Cody
ec0a77230c Prepare 6.0.2 2024-12-31 10:29:32 -08:00
Cody
b35e4bddd0 Prepare 6.0.2 2024-12-31 10:28:48 -08:00
Cody
aa32beb341 Update Oqtane.Shared.csproj 2024-12-31 10:28:32 -08:00
Cody
efafe89b42 Prepare 6.0.2 2024-12-31 10:26:45 -08:00
Cody
5ef2e49d9c Prepare 6.0.2 2024-12-31 10:25:34 -08:00
Cody
1cfbf61a30 Prepare 6.0.2 2024-12-31 10:23:15 -08:00
Cody
2bb5494b84 Prepare 6.0.2 2024-12-31 10:22:10 -08:00
Cody
e8a41ccb47 Prepare 6.0.2 2024-12-31 10:21:10 -08:00
Cody
7184f7f635 Prepare 6.0.2 and update package dependencies 2024-12-31 10:20:13 -08:00
Cody
cc5727b7fa Prepare 6.0.2 and update package dependencies 2024-12-31 10:16:35 -08:00
Shaun Walker
7f3d6ef6a5 Merge pull request #4959 from sbwalker/dev
fix #4957 - unable to login after password reset
2024-12-31 08:18:14 -05:00
sbwalker
44ce68097b fix #4957 - unable to login after password reset 2024-12-31 08:17:58 -05:00
Shaun Walker
d976cc6c19 Update SECURITY.md 2024-12-25 10:04:25 -05:00
Shaun Walker
d19d7d2a43 Merge pull request #4948 from zyhfish/task/fix-4947
Fix #4947: check the 2FA settings.
2024-12-24 08:46:43 -05:00
Shaun Walker
9bfaa02f97 Merge pull request #4953 from sbwalker/dev
add back System.Text.Json to Shared project (#4929)
2024-12-23 14:48:10 -05:00
sbwalker
2d9396b245 add back System.Text.Json to Shared project (#4929) 2024-12-23 14:47:17 -05:00
Shaun Walker
56e0da64ee Merge pull request #4952 from sbwalker/dev
updated default module template to use Service consistently
2024-12-23 14:10:07 -05:00
sbwalker
997e9213f2 updated default module template to use Service consistently 2024-12-23 14:09:54 -05:00
Shaun Walker
366569a23b Merge pull request #4951 from sbwalker/dev
update package references
2024-12-23 11:24:38 -05:00
sbwalker
36d5747b4f update package references 2024-12-23 11:24:24 -05:00
Shaun Walker
ea026c726c Merge pull request #4950 from sbwalker/dev
remove unnecessary reference to System.Text.Json in Shared project
2024-12-23 11:16:49 -05:00
sbwalker
1e71e32c74 remove unnecessary reference to System.Text.Json in Shared project 2024-12-23 11:16:34 -05:00
Shaun Walker
ed729bbd4f Merge pull request #4949 from sbwalker/dev
fix #4946 - allow administrators to access user roles via API
2024-12-23 09:27:04 -05:00
sbwalker
1a925221b7 fix #4946 - allow administrators to access user roles via API 2024-12-23 09:26:50 -05:00
Ben
af7b4db062 Fix #4947: check the 2FA settings. 2024-12-23 22:10:51 +08:00
Shaun Walker
cfefe35e3f Update README.md 2024-12-20 16:56:05 -05:00
Shaun Walker
8d7845a44d Merge pull request #4944 from oqtane/master
6.0.1 Release
2024-12-20 16:52:31 -05:00
Shaun Walker
3a15e6e5e9 Merge pull request #4943 from oqtane/dev
6.0.1 Release
2024-12-20 16:52:10 -05:00
Shaun Walker
3b8a51e855 Merge pull request #4942 from sbwalker/dev
fix reload script to use static array rather than a live HtmlCollection
2024-12-20 15:39:50 -05:00
sbwalker
f2cb34cc35 fix reload script to use static array rather than a live HtmlCollection 2024-12-20 15:39:35 -05:00
Shaun Walker
723ce62a34 Merge pull request #4940 from sbwalker/dev
write upgrade errors to log rather than console
2024-12-20 14:38:34 -05:00
sbwalker
2c9a2ea021 write upgrade errors to log rather than console 2024-12-20 14:38:21 -05:00
Shaun Walker
2be008d6d1 Merge pull request #4939 from sbwalker/dev
fix compilation issues in PR #4782
2024-12-20 12:36:24 -05:00
sbwalker
7fb51bdd0a fix compilation issues in PR #4782 2024-12-20 12:36:10 -05:00
Shaun Walker
abdbe3694f Merge pull request #4782 from thabaum/edit-add-page-scrolltotoppage-error
Fixes #4781: Adds Edit + Add Page ScrollToTopPage() On Settings Tab Form Error Messages
2024-12-20 12:26:55 -05:00
Shaun Walker
bd87e5012f Merge pull request #4938 from sbwalker/dev
fix documentation
2024-12-20 11:55:50 -05:00
sbwalker
55e18f2364 fix documentation 2024-12-20 11:55:35 -05:00
Shaun Walker
655e84072d Merge pull request #4937 from sbwalker/dev
use CompressionEnabled switch to disable static asset compression during publish - eliminates need to cleanup files manually in release.cmd
2024-12-20 11:46:52 -05:00
sbwalker
ab5409d5b6 use CompressionEnabled switch to disable static asset compression during publish - eliminates need to cleanup files manually in release.cmd 2024-12-20 11:46:30 -05:00
Shaun Walker
5a5da6486c Merge pull request #4933 from sbwalker/dev
remove *.br, *.gz files from wwwroot content folders in published release (as MapStaticAssets is not enabled)
2024-12-19 19:56:36 -05:00
sbwalker
7e99252429 remove *.br, *.gz files from wwwroot content folders in published release (as MapStaticAssets is not enabled) 2024-12-19 19:56:13 -05:00
Shaun Walker
10e0dcef8b Merge pull request #4931 from sbwalker/dev
ensure Pages collection is always returned in the same order by moving GetPagesHierarchy method to the repository
2024-12-19 14:45:34 -05:00
sbwalker
80c8433aad ensure Pages collection is always returned in the same order by moving GetPagesHierarchy method to the repository. 2024-12-19 14:45:12 -05:00
Shaun Walker
5b0ae372f8 Merge pull request #4930 from sbwalker/dev
add support for data-reload=false attribute in Interactive rendering
2024-12-19 13:04:59 -05:00
sbwalker
b5a1b529ab add support for data-reload=false attribute in Interactive rendering 2024-12-19 13:04:43 -05:00
Shaun Walker
af821dcd9a Merge pull request #4914 from leigh-pointer/userSettings
User Profile Update: Utilizing User Settings Object
2024-12-18 15:27:34 -05:00
Shaun Walker
10d3c81520 Merge pull request #4918 from leigh-pointer/ProjectNameTemplates
Implement Dynamic ProjectName Parameter Across Build Process
2024-12-18 15:27:24 -05:00
Shaun Walker
e3811b453a Merge pull request #4927 from sbwalker/dev
Improvements to add support for script type and data-* attributes. Also added Script and Stylesheet classes to simplify Resource declarations.
2024-12-18 15:16:16 -05:00
sbwalker
ca0fb05baa Improvements to add support for script type and data-* attributes. Also added Script and Stylesheet classes to simplify Resource declarations. 2024-12-18 15:15:54 -05:00
Shaun Walker
2b4b01bf6e Merge pull request #4926 from sbwalker/dev
always render page-script elements in body
2024-12-18 11:56:18 -05:00
sbwalker
3a1244bddc always render page-script elements in body 2024-12-18 11:56:03 -05:00
Shaun Walker
b8fd922b19 Merge pull request #4925 from sbwalker/dev
improve reload script to replicate all attributes
2024-12-18 10:32:12 -05:00
sbwalker
03f856025e improve reload script to replicate all attributes 2024-12-18 10:31:59 -05:00
Shaun Walker
45f04d24c3 Merge pull request #4924 from sbwalker/dev
refactor Static Blazor script processing
2024-12-18 10:09:20 -05:00
sbwalker
2435d610c7 refactor Static Blazor script processing 2024-12-18 10:09:02 -05:00
Shaun Walker
06572bcd14 Merge pull request #4922 from sbwalker/dev
page-script optimization
2024-12-17 14:57:17 -05:00
sbwalker
3fab79afc0 page-script optimization 2024-12-17 14:57:01 -05:00
Shaun Walker
2b7dd3fed5 Merge pull request #4921 from sbwalker/dev
render page-script elements at end of head content
2024-12-17 12:31:40 -05:00
sbwalker
d65efed032 render page-script elements at end of head content 2024-12-17 12:31:26 -05:00
Shaun Walker
c6896ea936 Merge pull request #4920 from sbwalker/dev
fix page-script to support type attribute on inline scripts
2024-12-17 09:13:42 -05:00
sbwalker
b7a41bddec fix page-script to support type attribute on inline scripts 2024-12-17 09:13:26 -05:00
Shaun Walker
6fd80c3737 Merge pull request #4919 from sbwalker/dev
page-script improvements
2024-12-17 08:34:55 -05:00
sbwalker
0aa690b3b1 page-script improvements 2024-12-17 08:34:39 -05:00
Leigh Pointer
6d5bcfc6ed Implement Dynamic ProjectName Parameter Across Build Process
This pull request introduces a dynamic ProjectName parameter across our build process, enhancing flexibility and reducing hardcoding in our module and theme development workflow. The changes affect the project file, NuSpec file, command scripts.
2024-12-17 10:35:14 +01:00
Shaun Walker
b60de69fa5 Merge pull request #4917 from sbwalker/dev
improvements to page-script
2024-12-16 12:44:23 -05:00
sbwalker
d991b57d08 improvements to page-script 2024-12-16 12:44:07 -05:00
Leigh Pointer
1133d7fcba User Profile Update: Utilizing User Settings Object
This pull request updates the User Profile implementation to utilize the existing User Settings object on the user object. While the current implementation is functional, this change offers several benefits:
Improved code consistency
Better guidance for developers accessing User Settings
Alignment with the framework's best practices
2024-12-14 11:09:54 +01:00
Shaun Walker
6fbf0383bb Merge pull request #4911 from leigh-pointer/FixGlow
This is a cosmetic fix to the Oqtane Glow image
2024-12-13 16:46:49 -05:00
Shaun Walker
0296230219 Merge pull request #4913 from sbwalker/dev
page-script enhancements
2024-12-13 16:46:23 -05:00
sbwalker
dedfbba27a page-script enhancements 2024-12-13 16:46:08 -05:00
Leigh Pointer
dc5441da07 This is a cosmetic fix to the Oqtane Glow image
The glow on the original is cropped at the left by a few pixcels.  This update fixes that and sizes the image to a 600 x 150
2024-12-13 11:45:13 +01:00
Shaun Walker
585648b7f3 Merge pull request #4907 from leigh-pointer/ProfileMaxLength
FIX for #4906 Profile Field does not allow max length
2024-12-10 09:12:52 -05:00
Leigh Pointer
cd0ee1c26d FIX for #4906 Profile Field does not allow max length
This update applies the maxlength attribute fix to all input and textarea elements. The maxlength attribute will only be added if p.MaxLength is greater than 0, allowing unlimited characters when it's 0 or less.
2024-12-10 09:25:01 +01:00
Shaun Walker
d7a7be5af4 Merge pull request #4904 from sbwalker/dev
add sync events for user login/logout
2024-12-09 10:55:55 -05:00
sbwalker
13e4267c11 add sync events for user login/logout 2024-12-09 10:55:40 -05:00
Shaun Walker
15bc47e3e8 Merge pull request #4898 from leigh-pointer/TemplateParam
Implement Dynamic TargetFramework in Debug Scripts #4897
2024-12-09 07:36:00 -05:00
Leigh Pointer
1a4380dcd7 Variable update 2024-12-07 15:02:27 +01:00
Leigh Pointer
5ace34b5cd Add the $TargetFramework macro to the Release Builds
Add the $TargetFramework macro to the Release Builds
2024-12-06 13:37:37 +01:00
Leigh Pointer
f010c0f1fa Implement Dynamic TargetFramework in Debug Scripts #4897
This PR updates our debug scripts (both .cmd and .sh) to dynamically use the current TargetFramework passed from the build process. This change improves flexibility and future-proofs our build process for different .NET versions.
2024-12-05 12:43:38 +01:00
Shaun Walker
2c721ad5dd Merge pull request #4895 from tvatavuk/enh-4883-control-panel
Add ShowEditMode parameter to ControlPanel to allow hiding the Edit Mode toggle button
2024-12-04 08:25:17 -05:00
Shaun Walker
8a7c2ce2c2 Merge pull request #4894 from W6HBR/dev
Fix #4885 - Pass userid as int to GetUser for JWT authentication
2024-12-04 08:24:27 -05:00
Tonći Vatavuk
b2a7b813de Remove redundant IServiceProvider injection 2024-12-04 09:39:02 +01:00
Tonći Vatavuk
e85cf04b99 Fix #4883: Add ShowEditMode parameter to ControlPanel to allow hiding the Edit Mode toggle button 2024-12-04 09:37:21 +01:00
Jon Welfringer
ab6fa48172 Fix #4885 - Pass userid as int to GetUser for JWT authentication 2024-12-03 10:34:44 -08:00
Shaun Walker
c81905882f Merge pull request #4881 from sbwalker/dev
improve security of UserRole API
2024-11-27 14:59:41 -05:00
sbwalker
f0d31c1114 improve security of UserRole API 2024-11-27 14:59:25 -05:00
Shaun Walker
497b255216 Merge pull request #4880 from sbwalker/dev
User Settings should only be accessible to individual users or administrators
2024-11-27 13:16:04 -05:00
sbwalker
d96286d771 User Settings should only be accessible to individual users or administrators 2024-11-27 13:15:43 -05:00
Shaun Walker
2441647d75 Merge pull request #4879 from sbwalker/dev
update EFCore.NamingConventions to .NET 9 package version
2024-11-27 13:06:53 -05:00
sbwalker
77b780d631 update EFCore.NamingConventions to .NET 9 package version 2024-11-27 13:06:37 -05:00
Shaun Walker
cdd03bf3d4 Merge pull request #4878 from sbwalker/dev
User Settings should only be accessible to individual users or administrators
2024-11-27 13:04:27 -05:00
sbwalker
e786c35f7d User Settings should only be accessible to individual users or administrators 2024-11-27 13:04:06 -05:00
Shaun Walker
e83399acb1 Merge pull request #4876 from sbwalker/dev
prevent notifications from being accessed by other users
2024-11-26 14:30:55 -05:00
sbwalker
ffea9e3210 prevent notifications from being accessed by other users 2024-11-26 14:30:41 -05:00
Shaun Walker
f71a3a1ce3 Merge pull request #4875 from oqtane/revert-4828-TabChange
Revert "Fix for Tabpanel is not updating the UI. #4778"
2024-11-26 13:36:18 -05:00
Shaun Walker
a5ccc23604 Revert "Fix for Tabpanel is not updating the UI. #4778" 2024-11-26 13:36:05 -05:00
Shaun Walker
1ed4c8a094 Merge pull request #4874 from oqtane/revert-4871-HTMLTabError
Revert "Rework for Tabstrip regression issue"
2024-11-26 13:35:37 -05:00
Shaun Walker
4a74549c1b Revert "Rework for Tabstrip regression issue" 2024-11-26 13:35:21 -05:00
Shaun Walker
a499cfb98f Merge pull request #4871 from leigh-pointer/HTMLTabError
Rework for Tabstrip regression issue
2024-11-26 11:27:52 -05:00
Shaun Walker
01038c8296 Merge pull request #4873 from sbwalker/dev
include SECURITY.md
2024-11-26 11:25:35 -05:00
sbwalker
7407f79b3d include SECURITY.md 2024-11-26 11:25:23 -05:00
Leigh Pointer
a845dd1976 Rework for Tabstrip regression issue
Fix for Tabpanel is not updating the UI. #4778 #4828
2024-11-26 15:39:51 +01:00
Leigh Pointer
9d7549da70 Reverted TabStrip and Panel 2024-11-26 10:33:18 +01:00
Shaun Walker
f5cc61384f Merge pull request #4870 from sbwalker/dev
reference Quill CSS theme using BaseUrl so that it works in .NET MAUI as well as web
2024-11-25 14:20:15 -05:00
sbwalker
844778d36a reference Quill CSS theme using BaseUrl so that it works in .NET MAUI as well as web 2024-11-25 14:19:58 -05:00
Shaun Walker
871b0a274e Merge pull request #4869 from sbwalker/dev
improve message grammar
2024-11-25 13:48:41 -05:00
sbwalker
737740a3ca improve message grammar 2024-11-25 13:48:28 -05:00
Shaun Walker
ae8d600600 Update README.md 2024-11-25 09:11:12 -05:00
Shaun Walker
2f1691bfb0 Update README.md 2024-11-25 09:10:20 -05:00
Shaun Walker
a3d25f91c8 Update README.md 2024-11-25 09:09:52 -05:00
Shaun Walker
ff84b50817 Update README.md 2024-11-25 09:09:13 -05:00
Shaun Walker
0be8242284 Merge pull request #4862 from leigh-pointer/SettingsSetTabOnSave
Updated the Module Settings to use the new ActiveTab parameter
2024-11-25 08:39:45 -05:00
Shaun Walker
e25a6259ea Merge pull request #4861 from zyhfish/task/fix-4841
Fix #4841: force 2FA validation when it's required in site level.
2024-11-25 08:39:26 -05:00
Leigh Pointer
1578f82efb Updated the Module Settings to use the new ActiveTab parameter 2024-11-23 11:42:22 +01:00
Ben
b5f75f0c5e Fix #4841: force 2FA validation when it's required in site level. 2024-11-23 13:04:27 +08:00
Shaun Walker
601caab3b6 Merge pull request #4860 from sbwalker/dev
fix #4760 - display update confirmation message in Site Settings
2024-11-22 16:34:46 -05:00
sbwalker
6d3092f440 fix #4760 - display update confirmation message in Site Settings 2024-11-22 16:34:35 -05:00
Shaun Walker
ef27937c7a Merge pull request #4785 from thabaum/refactored-heading-ifelse
Fixes #4784: Refactor TabPanel Heading Assignment Logic
2024-11-22 15:34:51 -05:00
Shaun Walker
f4a7b79c4f Merge pull request #4828 from leigh-pointer/TabChange
Fix for Tabpanel is not updating the UI. #4778
2024-11-22 15:30:51 -05:00
Shaun Walker
2531776a48 Merge pull request #4859 from sbwalker/dev
prepare for 6.0.1
2024-11-22 12:29:56 -05:00
sbwalker
ced80419aa prepare for 6.0.1 2024-11-22 12:29:44 -05:00
Shaun Walker
ad2816f4e8 Merge pull request #4858 from sbwalker/dev
fix #4848 - remove assemblies from /bin which have been moved to /bin/refs in .NET 9
2024-11-22 12:14:04 -05:00
sbwalker
3528b8c674 fix #4848 - remove assemblies from /bin which have been moved to /bin/refs in .NET 9 2024-11-22 12:13:45 -05:00
Shaun Walker
80c83c626d Merge pull request #4853 from leigh-pointer/PagerAlignment
Fix for #4852 align the Page numbers container
2024-11-22 11:56:12 -05:00
Shaun Walker
6a355f2aea Merge pull request #4857 from sbwalker/dev
fix #4855 - dropping required column causes issue on SQLite
2024-11-22 11:55:56 -05:00
sbwalker
7d94e4a53a fix #4855 - dropping required column causes issue on SQLite 2024-11-22 11:55:43 -05:00
Shaun Walker
823c04742e Merge pull request #4854 from sbwalker/dev
resolve .NET version issue in nuspec files
2024-11-21 10:54:06 -05:00
sbwalker
043fb1abd1 resolve .NET version issue in nuspec files 2024-11-21 10:53:52 -05:00
Leigh Pointer
f01e85b690 Fix for #4852 align the Page numbers container 2024-11-21 16:05:32 +01:00
Shaun Walker
7eb1298847 Merge pull request #4847 from sbwalker/dev
do not include Oqtane.Server.staticwebassets.endpoints.json in release packages
2024-11-19 13:50:05 -05:00
sbwalker
a5480c9a96 do not include Oqtane.Server.staticwebassets.endpoints.json in release packages 2024-11-19 13:49:45 -05:00
Shaun Walker
f948600e86 Merge pull request #4845 from sbwalker/dev
fix 2 factor authentication email
2024-11-18 15:04:01 -05:00
sbwalker
420182b9bf fix 2 factor authentication email 2024-11-18 15:03:48 -05:00
Shaun Walker
8c430ce1a6 Merge pull request #4837 from Trifoia/4803-Add-a-CONTRIBUTING.md
4803 add a contributing.md
2024-11-15 15:02:28 -05:00
Mark Davis
d3717dbe19 Remove DefaultDBType value and InstallationId from appsettings.json
The commit removes the value for DefaultDBType and InstallationId from the appsettings.json file.
2024-11-15 10:31:49 -08:00
Mark Davis
caa83d769f Create CONTRIBUTING.md 2024-11-15 10:27:53 -08:00
Mark Davis
365f87828f Merge remote-tracking branch 'oqtane/dev' into dev 2024-11-15 09:52:50 -08:00
Shaun Walker
f780887866 Update README.md 2024-11-14 15:46:26 -05:00
Shaun Walker
43627d4bb8 Merge pull request #4832 from oqtane/master
6.0.0 release
2024-11-14 15:40:38 -05:00
Shaun Walker
5d7b276cd1 Merge pull request #4831 from oqtane/dev
6.0.0 release
2024-11-14 15:40:17 -05:00
Shaun Walker
23597eb997 Merge pull request #4827 from leigh-pointer/Search-4824
Fix: for Disabling search does not hide search icon #4824
2024-11-14 07:54:52 -05:00
Shaun Walker
b6948367f8 Merge pull request #4826 from leigh-pointer/swash
Swashbuckle.AspNetCore updated to 7.0
2024-11-14 07:52:49 -05:00
Leigh Pointer
db6dd5abee Fix for TabPanel is not updating the UI. #4778
Modified that TabStrip and TabPane, now when the ActiveTab is changed the TabPanel is selected
2024-11-14 10:35:15 +01:00
Leigh Pointer
702eb9e466 Revert "Fix for Page Management tab panel is not updating the UI. #4778"
This reverts commit 3c99006226.
2024-11-14 10:33:10 +01:00
Leigh Pointer
3c99006226 Fix for Page Management tab panel is not updating the UI. #4778 2024-11-14 10:31:53 +01:00
Leigh Pointer
aaaf5683a5 Fix: "Search_Enabled" was being saved as Private so unauthorized users can not access this value. 2024-11-14 09:50:05 +01:00
Leigh Pointer
92aa2236c0 Swashbuckle.AspNetCore updated to 7.0 2024-11-14 09:16:55 +01:00
Shaun Walker
d2592f72d6 Merge pull request #4825 from sbwalker/dev
modifications to get .NET MAUI working on .NET 9 official release
2024-11-13 20:37:24 -05:00
sbwalker
27120d6cc9 modifications to get .NET MAUI working on .NET 9 official release 2024-11-13 20:37:10 -05:00
Shaun Walker
a2669d35c3 Merge pull request #4823 from sbwalker/dev
exclude wwwroot/_content from official release build
2024-11-13 14:14:47 -05:00
sbwalker
574164081b exclude wwwroot/_content from official release build 2024-11-13 14:14:35 -05:00
Shaun Walker
00c2f8dcd8 Merge pull request #4822 from sbwalker/dev
adjust gitignore to exclude wwwroot/_content subfolders
2024-11-13 13:52:08 -05:00
sbwalker
0202bf60e5 adjust gitignore to exclude wwwroot/_content subfolders 2024-11-13 13:51:54 -05:00
Shaun Walker
16436a171b Merge pull request #4821 from zyhfish/task/fix-build-error
add reference to Microsoft.EntityFrameworkCore package.
2024-11-13 10:10:19 -05:00
Ben
4cf4e0eabd add reference to Microsoft.EntityFrameworkCore package. 2024-11-13 23:06:43 +08:00
Shaun Walker
5edb98dfb4 Merge pull request #4818 from sbwalker/dev
update PostgreSQL provider to official .NET 9 release
2024-11-12 15:50:27 -05:00
sbwalker
899bf22e15 update PostgreSQL provider to official .NET 9 release 2024-11-12 15:50:13 -05:00
Shaun Walker
9a33167a6c Merge pull request #4817 from sbwalker/dev
Update to official .NET 9 release
2024-11-12 15:43:42 -05:00
sbwalker
2dc068aa21 upgrade to official .NET 9 release 2024-11-12 15:42:57 -05:00
sbwalker
0f2aa4d2e1 update to official .NET 9 release 2024-11-12 15:40:54 -05:00
Shaun Walker
a699f5c7bc Merge pull request #4815 from mdmontesinos/dev
Fix: Accesibility issue for Search Button
2024-11-12 15:08:23 -05:00
David Montesinos
ab807de3c0 Fix: Accesibility issue for Search Button
The search button in Search component does not have the aria-label.
2024-11-12 17:15:56 +01:00
Shaun Walker
68514bcb36 Merge pull request #4813 from sbwalker/dev
use HttpClient rather than IHttpClientFactory as IHttpClientFactory does not pass cookies in .NET MAUI
2024-11-11 08:15:14 -05:00
sbwalker
422bf8da59 use HttpClient rather than IHttpClientFactory as IHttpClientFactory does not pass cookies in .NET MAUI 2024-11-11 08:14:53 -05:00
Shaun Walker
de92dc93dd Merge pull request #4811 from sbwalker/dev
resolved issue when setting initial culture cookie
2024-11-08 15:41:36 -05:00
sbwalker
5a91b143b6 resolved issue when setting initial culture cookie 2024-11-08 15:41:24 -05:00
Shaun Walker
c745e85706 Merge pull request #4810 from sbwalker/dev
make indexing of Files opt-in rather than opt-out
2024-11-08 15:16:45 -05:00
sbwalker
0f698e0c50 make indexing of Files opt-in rather than opt-out 2024-11-08 15:16:32 -05:00
Shaun Walker
cd16d77bf0 Merge pull request #4809 from sbwalker/dev
Added defensive logic to File Indexer for scenarios where file does not exist on disk. Added ability to reset the search index prior to reindexing.
2024-11-07 17:05:48 -05:00
sbwalker
fdbdd0ef4c Added defensive logic to File Indexer for scenarios where file does not exist on disk. Added ability to reset the search index prior to reindexing. 2024-11-07 17:05:28 -05:00
Shaun Walker
71485f4a82 Merge pull request #4808 from sbwalker/dev
fix compilation warning
2024-11-07 15:45:47 -05:00
sbwalker
013056a6e5 fix compilation warning 2024-11-07 15:45:34 -05:00
Shaun Walker
263498fbdc Merge pull request #4807 from sbwalker/dev
remove icrosoft.AspNetCore.Localization from .NET MAUI project
2024-11-07 12:38:31 -05:00
sbwalker
f46ac2c007 remove icrosoft.AspNetCore.Localization from .NET MAUI project 2024-11-07 12:38:16 -05:00
Shaun Walker
c23841b6db Merge pull request #4806 from sbwalker/dev
default Description to Module Name if not specified in Module Creator
2024-11-07 11:53:15 -05:00
sbwalker
18b1b5fca5 default Description to Module Name if not specified in Module Creator 2024-11-07 11:52:53 -05:00
Shaun Walker
6707ac2697 Merge pull request #4802 from sbwalker/dev
remove custom JavaScript reconnection script for SignalR
2024-11-05 11:30:32 -05:00
sbwalker
d85a2fc8ce remove custom JavaScript reconnection script for SignalR 2024-11-05 11:30:18 -05:00
Shaun Walker
a8997e8f17 Merge pull request #4800 from sbwalker/dev
fix #4795 - ensure deterministic ordering of file parts when merging files after upload (credit @HQuast)
2024-11-04 15:29:16 -05:00
sbwalker
c8a22d9537 fix #4795 - ensure deterministic ordering of file parts when merging files after upload (credit @HQuast) 2024-11-04 15:28:59 -05:00
Shaun Walker
910669f786 Merge pull request #4793 from thabaum/patch-12
Fixes #4792: Update Oqtane.Server.csproj Package Dependencies
2024-11-01 15:40:14 -04:00
Cody
89312c6796 Update Oqtane.Server.csproj Package Dependencies 2024-10-30 18:43:42 -07:00
Shaun Walker
a6aa96fdb0 Merge pull request #4786 from sbwalker/dev
fix #4770 - set a default value for PrincipalSchema to ensure backward compatibility
2024-10-24 17:08:42 -04:00
sbwalker
7deb0b06af fix #4770 - set a default value for PrincipalSchema to ensure backward compatibility 2024-10-24 17:08:25 -04:00
Cody
784f3771b3 Remove Blank Page Specific Error Message 2024-10-24 13:22:08 -07:00
Cody
80316824f7 Remove Blank Page Specific Error Message 2024-10-24 13:21:40 -07:00
Cody
cbaebb7b7c Remove Blank Page Specific Error Message 2024-10-24 13:21:15 -07:00
Cody
97d3764b6e Remove Blank Page Specific Error Message 2024-10-24 13:20:52 -07:00
Shaun Walker
002f8117cb Merge pull request #4783 from sbwalker/dev
get language using CookieRequestCultureProvider
2024-10-24 15:48:28 -04:00
sbwalker
0dfdb12431 get language using CookieRequestCultureProvider 2024-10-24 15:48:14 -04:00
Cody
d77e898929 Refactor TabPanel Heading Assignment Logic
- Simplified the logic for setting the Heading property in the TabPanel component.
- Replaced the if-else statement with a ternary operator for improved readability and maintainability.
- Ensured that the functionality remains unchanged and verified correct assignment of headings.
2024-10-24 12:43:20 -07:00
Cody
4c937be884 Clarify Page Name Required Message 2024-10-24 12:38:51 -07:00
Cody
c25cce4398 Clarify Page Name Required Message 2024-10-24 12:38:16 -07:00
Cody
58c422285a Adds Message.Required.PageName 2024-10-24 12:28:17 -07:00
Cody
f2f22f35e8 Adds Message.Required.PageName 2024-10-24 12:26:36 -07:00
Cody
15867a7807 Adds await ScrollToPageTop(); to error messages + Page Name Error Message 2024-10-24 12:23:29 -07:00
Shaun Walker
22e3161a9b Merge pull request #4780 from sbwalker/dev
remove Microsoft.AspNetCore.Localization from default module template
2024-10-24 15:20:20 -04:00
sbwalker
b0c8203b24 remove Microsoft.AspNetCore.Localization from default module template 2024-10-24 15:20:07 -04:00
Cody
e2c404d8bb Adds await ScrollToPageTop(); to error messages + Page Name Error Message
- Adds await ScrollToPageTop(); to error messages
- Adds Blank Page Name Error Message
2024-10-24 12:18:30 -07:00
Shaun Walker
5ee1731c92 Merge pull request #4777 from thabaum/update-html-agility-pack-1.11.69
Fixes #4776: Updates HtmlAgilityPack to 1.11.69
2024-10-24 15:12:17 -04:00
Shaun Walker
06e8d3b660 Merge pull request #4779 from sbwalker/dev
remove Microsoft.AspNetCore.Http
2024-10-24 15:11:07 -04:00
sbwalker
f09709aedb remove Microsoft.AspNetCore.Http 2024-10-24 15:10:52 -04:00
Cody
598d5decac Update HtmlAgilityPack to 1.11.69 2024-10-24 10:18:24 -07:00
Shaun Walker
7832a6053e Merge pull request #4775 from sbwalker/dev
remove some dependencies on Microsoft.AspNetCore.Http
2024-10-24 13:16:21 -04:00
sbwalker
588748230e remove some dependencies on Microsoft.AspNetCore.Http 2024-10-24 13:16:08 -04:00
Shaun Walker
8668165c72 Merge pull request #4774 from sbwalker/dev
remove Microsoft.AspNetCore.Localization
2024-10-24 12:25:04 -04:00
sbwalker
a967332f89 remove Microsoft.AspNetCore.Localization 2024-10-24 12:24:46 -04:00
Shaun Walker
6719d242bd Merge pull request #4756 from zyhfish/task/fix-4752
Fix #4752: validate the username and email.
2024-10-24 09:53:24 -04:00
Ben
3565185808 update the error message. 2024-10-24 20:13:43 +08:00
Ben
ce51262197 update the code to use simple validation. 2024-10-24 20:04:18 +08:00
Shaun Walker
992a786c2b Merge pull request #4763 from thabaum/ScrollTo-interop-modal
Fixes #4762: Adds logic ScrollTo interop.js method detecting if method is executed inside a modal
2024-10-22 16:28:45 -04:00
Shaun Walker
038df95aa0 Merge pull request #4759 from thabaum/scroll-to-top-user-settings
Scroll to top after saving settings - Fixes #4758
2024-10-22 16:28:33 -04:00
Shaun Walker
4ebd660de2 Merge pull request #4766 from sbwalker/dev
resolve compiler warning in .NET MAUI
2024-10-21 15:42:08 -04:00
sbwalker
a9ea41a488 resolve compiler warning in .NET MAUI 2024-10-21 15:41:57 -04:00
Shaun Walker
196594b490 Merge pull request #4765 from sbwalker/dev
update MAUI project to .NET 9 RC2
2024-10-21 15:34:34 -04:00
sbwalker
1516d5af10 update MAUI project to .NET 9 RC2 2024-10-21 15:34:22 -04:00
Shaun Walker
ffcd1595a9 Merge pull request #4764 from sbwalker/dev
update Updater to .NET 9
2024-10-21 15:25:27 -04:00
sbwalker
42e5c6e111 update Updater to .NET 9 2024-10-21 15:25:14 -04:00
Cody
8a9651dc50 Adds logic for .modal class ScrollTo function 2024-10-21 12:22:01 -07:00
Shaun Walker
4be2f4f2d9 Update README.md 2024-10-21 15:21:29 -04:00
Cody
369bf7a235 Adds logic for .modal class ScrollTo function
fixes #4762
2024-10-21 12:20:24 -07:00
Shaun Walker
136545b404 Merge pull request #4761 from sbwalker/dev
changes to migrate Oqtane to .NET 9 and version 6.0.0
2024-10-21 14:51:38 -04:00
sbwalker
73ea17ae0f changes to migrate Oqtane to .NET 9 and version 6.0.0 2024-10-21 14:51:20 -04:00
Cody
23010acef4 Scroll to top after saving settings - Fixes #4758 2024-10-21 10:36:12 -07:00
Ben
4f74962ce2 Fix #4752: validate the username and email. 2024-10-21 23:11:57 +08:00
Shaun Walker
7f978c7845 Update README.md 2024-10-17 13:52:21 -04:00
Shaun Walker
731fd46ea2 Merge pull request #4747 from oqtane/master
5.2.4 release
2024-10-17 13:46:40 -04:00
Shaun Walker
859759d691 Merge pull request #4746 from oqtane/dev
5.2.4 release
2024-10-17 13:46:22 -04:00
Shaun Walker
5e9567158f Merge pull request #4744 from sbwalker/dev
add additional external login providers
2024-10-16 08:35:14 -04:00
sbwalker
51d244f3aa add additional external login providers 2024-10-16 08:35:01 -04:00
Shaun Walker
4c5a07edd5 Merge pull request #4743 from sbwalker/dev
add missing localization keys
2024-10-16 07:52:49 -04:00
sbwalker
8113a754a1 add missing localization keys 2024-10-16 07:52:36 -04:00
Shaun Walker
3cd40c6195 Merge pull request #4742 from sbwalker/dev
fix sorting of Site.Languages property
2024-10-15 16:46:16 -04:00
sbwalker
56cfb2ce06 fix sorting of Site.Languages property 2024-10-15 16:46:05 -04:00
Shaun Walker
72087823ac Merge pull request #4741 from sbwalker/dev
fix #4733 - remove Name column from Language table and populate value dynamically
2024-10-15 16:44:44 -04:00
sbwalker
bcf7866fe2 fix #4733 - remove Name column from Language table and populate value dynamically 2024-10-15 15:58:17 -04:00
Shaun Walker
b64772e484 Merge pull request #4739 from thabaum/add-discord-community
Fixes #4738 - Add Discord community button to README.md
2024-10-15 15:26:32 -04:00
Cody
088d665942 Update Discord Community Link For Consistency 2024-10-15 10:27:59 -07:00
Cody
7d6c10befb Add Discord community button to README.md
- Added a button for joining the Oqtane Discord server
- Included a brief description encouraging community engagement
2024-10-15 10:17:01 -07:00
Shaun Walker
f88e3d04b8 Merge pull request #4736 from thabaum/mysql.data-9.1.0
Fixes #4735 - Update MySQL.Data to 9.1.0
2024-10-15 12:06:50 -04:00
Cody
f57676a22b Update MySQL.Data to 9.1.0 2024-10-15 08:15:52 -07:00
Shaun Walker
8618cb62e4 Merge pull request #4732 from sbwalker/dev
fix #4711 - full page refresh required to affect language changes
2024-10-15 08:32:08 -04:00
sbwalker
c31c88ed1f fix #4711 - full page refresh required to affect language changes 2024-10-15 08:31:54 -04:00
Shaun Walker
6022acd21f Merge pull request #4731 from sbwalker/dev
fix #4716 - sort recycle bin items by DeletedOn date descending
2024-10-15 07:56:07 -04:00
sbwalker
b3071b9272 fix #4716 - sort recycle bin items by DeletedOn date descending 2024-10-15 07:55:54 -04:00
Shaun Walker
ec6a6d6653 Merge pull request #4729 from sbwalker/dev
localize names of languages based on user's UI culture
2024-10-14 17:18:09 -04:00
sbwalker
52f552b4de localize names of languages based on user's UI culture 2024-10-14 17:17:54 -04:00
Shaun Walker
2643d3396b Merge pull request #4728 from sbwalker/dev
set HttpOnly to false for Localization cookie in static rendering
2024-10-14 16:49:27 -04:00
sbwalker
62d59a09cf set HttpOnly to false for Localization cookie in static rendering 2024-10-14 16:49:14 -04:00
Shaun Walker
a68ff8a4f0 Merge pull request #4727 from sbwalker/dev
When displaying Database Type use SQL Server rather than LocalDB to avoid confusion
2024-10-14 16:21:25 -04:00
sbwalker
93d4bfcd7a When displaying Database Type use SQL Server rather than LocalDB to avoid confusion 2024-10-14 16:21:03 -04:00
Shaun Walker
5fb80c1a7b Merge pull request #4726 from sbwalker/dev
fix #4722 - support PrincipalSchema when creating foreign keys (credit @Hypnodude)
2024-10-14 15:36:54 -04:00
sbwalker
04b38444ce fix #4722 - support PrincipalSchema when creating foreign keys (credit @Hypnodude) 2024-10-14 15:36:32 -04:00
Shaun Walker
ca3df02002 Merge pull request #4723 from mdmontesinos/dev
Image Resizing and Format via QueryString in Files Page (enhances #4692)
2024-10-14 15:20:37 -04:00
Shaun Walker
d952c33fab Merge pull request #4725 from sbwalker/dev
fix #4714 as well as breaking change in #4712
2024-10-14 15:05:59 -04:00
sbwalker
93bc1cd5af fix #4714 as well as breaking change in #4712 2024-10-14 15:05:46 -04:00
Shaun Walker
0e5b370ee8 Merge pull request #4712 from thabaum/language-switcher-cookie
Fix #4710 - Adds language switcher component cookie set options for secure, httpOnly, sameSite + interop.cs/interop.js methods samesite and secure options
2024-10-14 14:41:18 -04:00
Shaun Walker
f4fd4e28c9 Merge pull request #4724 from sbwalker/dev
update MAUI project to .NET 8.0.10
2024-10-14 13:12:09 -04:00
sbwalker
ec8433eb45 update MAUI project to .NET 8.0.10 2024-10-14 13:11:55 -04:00
Shaun Walker
0d4a40e9bb Merge pull request #4715 from leigh-pointer/CompUpdate-8.0.10
Updated Microsoft Components for 8.0.8 to 8.0.10
2024-10-14 13:04:54 -04:00
Shaun Walker
c3668f4179 Merge pull request #4708 from thabaum/patch-10
fix typo in startup.cs
2024-10-14 12:48:38 -04:00
David Montesinos
3adb7ecb1c Enhances image manipulation with format (webp encoder, defaults to png)
- computes etag with all manipulation parameters
2024-10-13 17:20:18 +02:00
David Montesinos
aa5b84a214 Implements Image Manipulation in Files Page via QueryString
- Extracts the image creation into a service
- Refactors Files Page GET action for better readability and cyclomatic complexity
2024-10-13 12:38:43 +02:00
Leigh Pointer
3d83fccbf1 remove appsettings 2024-10-09 15:07:57 +02:00
Leigh Pointer
4c4255be6b Updated Template files with new component version 8.0.10 2024-10-09 14:42:07 +02:00
Leigh Pointer
ed6054b082 Updated Microsoft Components for 8.0.8 to 8.0.10
Tested on upgrade and new Oqtane instance creation.
2024-10-09 14:35:27 +02:00
Cody
f60f7a4dc1 Remove httpOnly setting from setCookie 2024-10-05 14:17:20 -07:00
Cody
998dc95cb2 Removed extra attribute for interop.SetCookie 2024-10-05 14:08:16 -07:00
Cody
12f5d7b846 Remove extra attribute for SetCookie 2024-10-05 14:06:35 -07:00
Cody
906ae0a43e Remove extra attribute for SetCookie 2024-10-05 14:06:18 -07:00
Cody
485b774876 Remove httpOnly cooking attribute from SetCookie 2024-10-05 14:03:20 -07:00
Cody
3121cf5b75 Remove unnecessary httpOnly setCookie option 2024-10-05 14:00:18 -07:00
Cody
ce7570dae2 Remove Unnecessary httpOnly setting setCookie Option 2024-10-05 13:58:55 -07:00
Cody
b5ea0dfbc7 Update Cleanup "setCookie" function notes options: secure, httpOnly, Samesite 2024-10-05 13:57:36 -07:00
Cody
dd0f8f4772 Update SetCookie function to include secure, httpOnly and sameSite 2024-10-05 13:55:35 -07:00
Cody
9d0ab34274 Update 'SetCookie" option settings "secure, httpOnly, sameSite" 2024-10-05 13:28:33 -07:00
Cody
e6038be6f7 Update SetCookie Option Settings Secure, HttpOnly, SameSite 2024-10-05 13:27:14 -07:00
Cody
bd2153a0ed Update cookie options to set SameSite, HttpOnly, Secure settings 2024-10-05 13:23:09 -07:00
Cody
e526deac20 Update Cookie Settings Secure, httpOnly, sameSite 2024-10-05 13:19:52 -07:00
Cody
b65f165dcf Update adds SameSite, Secure and httpOnly SetCookie Settings 2024-10-05 13:17:31 -07:00
Cody
f9fbe5adc2 Update NavigateTo() to use "true" instead of "forceLoad: true" 2024-10-05 12:11:52 -07:00
Cody
d1e73571a1 fix typo 2024-10-05 11:12:01 -07:00
Shaun Walker
1047058676 Merge pull request #4705 from maurocavallin/dev
Hard deletion of page more robust use of entity framework contexts
2024-10-04 17:14:00 -04:00
mauroc
29a1e77da8 Hard deletion of page more robust use of contexts (fixes issue: presence of stale records of deleted page on db). 2024-10-04 22:46:40 +02:00
Shaun Walker
290547e482 Merge pull request #4702 from sbwalker/dev
add defensive logic if ModuleState is null  in ModuleMessage
2024-10-02 16:53:46 -04:00
sbwalker
3df45ca20f add defensive logic if ModuleState is null in ModuleMessage 2024-10-02 16:53:36 -04:00
Shaun Walker
cc06258484 Merge pull request #4701 from sbwalker/dev
updated version to 5.2.4
2024-10-02 16:39:45 -04:00
sbwalker
2c262d0655 updated version to 5.2.4 2024-10-02 16:39:31 -04:00
Shaun Walker
1875e1e158 Merge pull request #4696 from sbwalker/dev
fix #4695 - null reference exception deleting a setting which does not exist
2024-10-02 08:30:58 -04:00
sbwalker
1c95967b31 fix #4695 - null reference exception deleting a setting which does not exist 2024-10-02 08:30:34 -04:00
Shaun Walker
2ae98929de Merge pull request #4689 from thabaum/Update-Dependencies-and-Prepare-Release-5.2.4
Fixes #4688 - Update dependencies and prepare release 5.2.4
2024-10-01 11:21:35 -04:00
Shaun Walker
6a1dd38cbb Merge pull request #4691 from zyhfish/task/fix-4690
Fix #4690: prevent invalid parsing.
2024-10-01 11:20:01 -04:00
Ben
c458a77d27 Fix #4690: prevent invalid parsing. 2024-10-01 22:13:32 +08:00
Cody
352c23f389 Prepare Release 5.2.4 2024-10-01 06:15:46 -07:00
Cody
6c5a1dc2e1 Prepare Release 5.2.4 2024-10-01 06:14:57 -07:00
Cody
004ff1e91d Update Dependencies and Prepare Release 5.2.4 2024-10-01 06:14:07 -07:00
Cody
f7de4c567b Prepare Release 5.2.4 2024-10-01 06:12:07 -07:00
Cody
b2ad1010ac Prepare Release 5.2.4 2024-10-01 06:11:36 -07:00
Cody
660e164ff8 Prepare Release 5.2.4 2024-10-01 06:11:04 -07:00
Cody
eb6dc80b50 Prepare Release 5.2.4 - removed whitespace 2024-10-01 06:10:21 -07:00
Cody
a9882cc96a Update Oqtane.Shared.nuspec 2024-10-01 06:09:35 -07:00
Cody
fb5a2ce178 Prepare Release 5.2.4 2024-10-01 06:09:12 -07:00
Cody
d441b31dc7 Prepare Release 5.2.4 2024-10-01 06:08:46 -07:00
Cody
d4239fe7e0 Prepare Release 5.2.4 2024-10-01 06:07:55 -07:00
Cody
6a98999105 Prepare Release 5.2.4 2024-10-01 06:06:03 -07:00
Cody
5caa1fe7d4 Prepare Release 5.2.4 2024-10-01 06:05:07 -07:00
Cody
ef33bdb65e Prepare Release 5.2.4 2024-10-01 06:04:11 -07:00
Cody
14a463382b Prepare Release 5.2.4 2024-10-01 06:03:20 -07:00
Cody
1ad79874c8 Update Dependencies and Prepare Release 5.2.4 2024-10-01 06:02:40 -07:00
Cody
1a61a58d28 Prepare Release 5.2.4 2024-10-01 06:00:20 -07:00
Cody
3e3c973679 Prepare Release 5.2.4 2024-10-01 05:59:47 -07:00
Cody
9dede84d20 Update Dependencies and Prepare Release 5.2.4 2024-10-01 05:57:17 -07:00
Shaun Walker
e78b11cf62 Merge pull request #4687 from sbwalker/dev
add some clarity to the database fields help text
2024-09-30 13:32:08 -04:00
sbwalker
341ca5a330 add some clarity to the database fields help text 2024-09-30 13:31:57 -04:00
Shaun Walker
e5d8c02def Merge pull request #4686 from sbwalker/dev
add validation of recipient email address to Notification job
2024-09-30 11:27:59 -04:00
sbwalker
947aa08c42 add validation of recipient email address to Notification job 2024-09-30 11:27:47 -04:00
Shaun Walker
9a04d436bd Merge pull request #4683 from sbwalker/dev
simplify configuration of external login providers
2024-09-27 16:21:23 -04:00
sbwalker
be0754f568 simplify configuration of external login providers 2024-09-27 16:21:06 -04:00
Shaun Walker
93c4bbc0d1 Merge pull request #4682 from sbwalker/dev
fix #4654 - show progress indicator during download
2024-09-27 12:01:07 -04:00
sbwalker
b98535810b fix #4654 - show progress indicator during download 2024-09-27 12:00:49 -04:00
Shaun Walker
393cf8da1f Merge pull request #4681 from sbwalker/dev
add disclaimer to System Update feature
2024-09-27 09:00:15 -04:00
sbwalker
ea2846973a add disclaimer to System Update feature 2024-09-27 09:00:04 -04:00
Shaun Walker
3398c1cbfe Merge pull request #4678 from sbwalker/dev
remove unnecessary using statement
2024-09-26 15:54:35 -04:00
sbwalker
39c79ea68e remove unnecessary using statement 2024-09-26 15:54:22 -04:00
Shaun Walker
66900f4a32 Merge pull request #4677 from sbwalker/dev
sign out the principal when it is rejected due to security stamp changes
2024-09-26 15:53:55 -04:00
sbwalker
df71dd14f7 sign out the principal when it is rejected due to security stamp changes 2024-09-26 15:53:14 -04:00
Shaun Walker
8113ca3069 Merge pull request #4676 from sbwalker/dev
fix #4657 - Cannot add new site to existing installation using separate database On IIS
2024-09-26 14:07:11 -04:00
sbwalker
d468e675c2 fix #4657 - Cannot add new site to existing installation using separate database On IIS 2024-09-26 14:06:51 -04:00
Shaun Walker
1e84cedf82 Merge pull request #4674 from sbwalker/dev
fix localization spelling mistake
2024-09-26 13:46:41 -04:00
sbwalker
7f4087e3de fix localization spelling mistake 2024-09-26 13:46:29 -04:00
Shaun Walker
facd3c8956 Merge pull request #4673 from sbwalker/dev
fix remote login issue which could occut if multiple users have the same email address
2024-09-26 13:38:30 -04:00
sbwalker
3e50deecb7 fix remote login issue which could occut if multiple users have the same email address 2024-09-26 13:37:39 -04:00
Shaun Walker
628c504f84 Merge pull request #4672 from sbwalker/dev
fix #4667 - installation issues when running on IIS
2024-09-26 13:33:31 -04:00
sbwalker
e1ada78c1f fix #4667 - installation issues when running on IIS 2024-09-26 13:33:16 -04:00
Shaun Walker
09fa1e365c Merge pull request #4670 from thabaum/remove-unnecessary-usings
Fixes #4669 - Remove unnecessary usings in IMultiDatabase.cs
2024-09-26 13:32:33 -04:00
Cody
28b6b03d06 Remove unnecessary usings 2024-09-25 15:13:06 -07:00
Shaun Walker
a4395b62ff Merge pull request #4668 from sbwalker/dev
fix #4666 - scroll position in enhanced navigation
2024-09-25 17:06:03 -04:00
sbwalker
4511acf273 fix #4666 - scroll position in enhanced navigation 2024-09-25 17:05:53 -04:00
Shaun Walker
fde53a2d83 Update README.md 2024-09-23 16:33:41 -04:00
Shaun Walker
f6cd04fdb8 Merge pull request #4662 from oqtane/master
Merge pull request #4661 from oqtane/dev
2024-09-23 16:26:39 -04:00
Shaun Walker
a5eede6c7a Merge pull request #4661 from oqtane/dev
5.2.3 release
2024-09-23 16:26:24 -04:00
Shaun Walker
2e83817c83 Merge pull request #4660 from sbwalker/dev
prepare for 5.2.3
2024-09-23 16:18:10 -04:00
sbwalker
82aea40ae4 prepare for 5.2.3 2024-09-23 16:17:55 -04:00
Shaun Walker
1b289eae24 Merge pull request #4659 from sbwalker/dev
use RoleName rather than RoleId for consistency
2024-09-23 16:08:02 -04:00
sbwalker
81420b2c88 use RoleName rather than RoleId for consistency 2024-09-23 16:07:49 -04:00
Shaun Walker
775731b745 Merge pull request #4657 from thabaum/patch-9
FIX #4655 - autocomplete="off" for SMTP Username/Password
2024-09-23 15:44:06 -04:00
Shaun Walker
489e7d4a67 Merge pull request #4658 from sbwalker/dev
fix RoleId missing from Permission Clone method
2024-09-23 15:38:51 -04:00
sbwalker
b6508764d8 fix RoleId missing from Permission Clone method 2024-09-23 15:38:35 -04:00
Cody
6dedd87305 autocomplete="off" for SMTP Username/Password 2024-09-23 12:19:49 -07:00
Shaun Walker
89fa29b310 Merge pull request #4653 from sbwalker/dev
improve scroll position script
2024-09-23 09:55:59 -04:00
sbwalker
be5df9c22a improve scroll position script 2024-09-23 09:55:44 -04:00
Shaun Walker
db17739716 Update README.md 2024-09-23 07:48:14 -04:00
Shaun Walker
1439362a5e Merge pull request #4651 from oqtane/master
5.2.2 Release
2024-09-23 07:39:21 -04:00
Shaun Walker
65c1b04772 Merge pull request #4650 from oqtane/dev
5.2.2 Release
2024-09-23 07:39:02 -04:00
Shaun Walker
83d30ebdc4 Merge pull request #4645 from sbwalker/dev
fix #4638 - add Logout Everywhere option to User Profile
2024-09-20 15:18:38 -04:00
sbwalker
b7928a5255 fix #4638 - add Logout Everywhere option to User Profile 2024-09-20 15:18:25 -04:00
Shaun Walker
a83ff9253d Merge pull request #4644 from sbwalker/dev
fix code formatting
2024-09-20 12:54:44 -04:00
sbwalker
8cdcdaf6d9 fix code formatting 2024-09-20 12:54:34 -04:00
Shaun Walker
d208edf153 Merge pull request #4643 from sbwalker/dev
fix #4641 - highlight default site theme in list of themes in page management
2024-09-20 12:28:06 -04:00
sbwalker
8ada4765b1 fix #4641 - highlight default site theme in list of themes in page management 2024-09-20 12:27:49 -04:00
Shaun Walker
9d3a808c24 Merge pull request #4642 from sbwalker/dev
fix #4826 - improve url handling
2024-09-20 12:09:16 -04:00
sbwalker
828eb80266 fix #4826 - improve url handling 2024-09-20 12:09:04 -04:00
Shaun Walker
0639f6c1d1 Merge pull request #4640 from sbwalker/dev
fix #4628 - preserve Url for all ModuleActions
2024-09-19 14:09:55 -04:00
sbwalker
49b971280f fix #4628 - preserve Url for all ModuleActions 2024-09-19 14:09:45 -04:00
Shaun Walker
3682a1010d Merge pull request #4637 from sbwalker/dev
synchronize interop.js with .NET MAUI
2024-09-19 12:14:36 -04:00
sbwalker
f8b58866dc synchronize interop.js with .NET MAUI 2024-09-19 12:14:24 -04:00
Shaun Walker
5d8d815d84 Merge pull request #4636 from zyhfish/task/4610-loadjs-issue
Fix #4610: wait for js loaded.
2024-09-19 12:10:55 -04:00
Ben
67743c7597 Fix #4610: wait for js loaded. 2024-09-19 23:34:59 +08:00
Shaun Walker
b33cc90447 Merge pull request #4635 from sbwalker/dev
use deep cloning to not muttate cache
2024-09-19 09:41:24 -04:00
sbwalker
78177f7890 use deep cloning to not muttate cache 2024-09-19 09:41:11 -04:00
Shaun Walker
3c417bfa99 Merge pull request #4633 from sbwalker/dev
fix trimming of site, page, and module settings
2024-09-18 18:32:04 -04:00
sbwalker
f2c8d80ff8 fix trimming of site, page, and module settings 2024-09-18 18:31:40 -04:00
Shaun Walker
8c1eb1e19f Merge pull request #4632 from sbwalker/dev
fix #4257 - load settings resources
2024-09-18 15:22:58 -04:00
sbwalker
eb7188e81b fix #4257 - load settings resources 2024-09-18 15:22:44 -04:00
Shaun Walker
f352fc5c67 Merge pull request #4631 from sbwalker/dev
on .NET MAUI provide message to user if Security Token has not been configured
2024-09-18 11:28:30 -04:00
sbwalker
ac313722f9 on .NET MAUI provide message to user if Security Token has not been configured 2024-09-18 11:28:11 -04:00
Shaun Walker
64c7f1962c Merge pull request #4630 from zyhfish/task/sync-maui-resources
sync changes to maui resources.
2024-09-18 10:46:34 -04:00
Ben
c83f994b21 sync changes to maui resources. 2024-09-18 22:44:14 +08:00
Shaun Walker
10f38a72f7 Merge pull request #4629 from sbwalker/dev
fix #4628 - preserve ReturnUrl when navigating to Settings component
2024-09-18 09:43:11 -04:00
sbwalker
da35434f58 fix #4628 - preserve ReturnUrl when navigating to Settings component 2024-09-18 09:42:56 -04:00
Shaun Walker
c79409e094 Merge pull request #4627 from sbwalker/dev
use FileLogger as fallback in LogManager when site cannot be determined
2024-09-18 07:38:20 -04:00
sbwalker
355ce00968 use FileLogger as fallback in LogManager when site cannot be determined 2024-09-18 07:37:52 -04:00
Shaun Walker
56c832f3ba Merge pull request #4626 from sbwalker/dev
fix logic to force authenticated user to provide email address so it works in static rendering
2024-09-17 17:29:30 -04:00
sbwalker
40abb2720e fix logic to force authenticated user to provide email address so it works in static rendering 2024-09-17 17:29:11 -04:00
Shaun Walker
9b6051afee Merge pull request #4625 from sbwalker/dev
update nuget.exe to latest and fix nuspec specification of readme
2024-09-17 15:19:57 -04:00
sbwalker
dcf6f26792 update nuget.exe to latest and fix nuspec specification of readme 2024-09-17 15:19:40 -04:00
Shaun Walker
85734c1146 Merge pull request #4624 from sbwalker/dev
remove unecessary using
2024-09-17 11:54:33 -04:00
sbwalker
c3fb8fcb6e remove unecessary using 2024-09-17 11:54:21 -04:00
Shaun Walker
013bbc1638 Merge pull request #4623 from sbwalker/dev
fix external login
2024-09-17 11:53:47 -04:00
sbwalker
b0669a3b60 fix external login 2024-09-17 11:53:34 -04:00
Shaun Walker
6f5da1ce7c Merge pull request #4622 from sbwalker/dev
allow external login to support SecurityStamp
2024-09-17 09:28:47 -04:00
sbwalker
3351732a2f allow external login to support SecurityStamp 2024-09-17 09:28:35 -04:00
Shaun Walker
d4d4034ecd Merge pull request #4621 from sbwalker/dev
remove unecessary usings
2024-09-17 09:07:57 -04:00
sbwalker
b45e2742c3 remove unecessary usings 2024-09-17 09:07:45 -04:00
Shaun Walker
42eba290e4 Merge pull request #4620 from sbwalker/dev
allow JwtMiddleware to support SecurityStamp
2024-09-17 09:07:14 -04:00
sbwalker
32d1e08b57 allow JwtMiddleware to support SecurityStamp 2024-09-17 09:06:49 -04:00
Shaun Walker
7b7d19da7c Merge pull request #4619 from sbwalker/dev
fix commented logic
2024-09-17 08:55:09 -04:00
sbwalker
f78e400918 fix commented logic 2024-09-17 08:54:52 -04:00
Shaun Walker
be4e9bf7e9 Merge pull request #4618 from sbwalker/dev
fix #4580 - add logout everywhere support using SecurityStamp
2024-09-17 08:45:41 -04:00
sbwalker
48f2079f88 fix #4580 - add logout everywhere support using SecurityStamp 2024-09-17 08:45:27 -04:00
Shaun Walker
36ad1ceef2 Merge pull request #4617 from sbwalker/dev
fix #4607 - site level scripts added twice in static rendering
2024-09-16 13:22:10 -04:00
sbwalker
1f2e2148d5 fix #4607 - scripts added twice 2024-09-16 13:21:43 -04:00
Shaun Walker
76f3d345f9 Merge pull request #4616 from sbwalker/dev
include SecurityStamp in User object
2024-09-16 13:03:32 -04:00
sbwalker
f2c854b53a include SecurityStamp in User object 2024-09-16 13:03:21 -04:00
Shaun Walker
e2d336d90b Merge pull request #4613 from sbwalker/dev
further modifications for #4604 - support for site name in logo component
2024-09-15 09:30:24 -04:00
sbwalker
c74065ff26 further modifications for #4604 - support for site name in logo component 2024-09-15 09:30:04 -04:00
Shaun Walker
b6d97dc5d5 Merge pull request #4612 from sbwalker/dev
fix #4606 - allow logo to show site name as fallback (credit @JanOlsmar)
2024-09-13 16:13:14 -04:00
sbwalker
1c1c26948a fix #4606 - allow logo to show site name as fallback (credit @JanOlsmar) 2024-09-13 16:13:01 -04:00
Shaun Walker
d954e3ffb7 Merge pull request #4608 from hishamco/toggle-edit-mode
Fix issue in toggle edit mode
2024-09-13 15:54:37 -04:00
Shaun Walker
d9759a95eb Merge pull request #4611 from sbwalker/dev
fix #4607 - Site HeadContent scripts being added twice
2024-09-13 15:19:31 -04:00
sbwalker
d196402dd0 fix #4607 - Site HeadContent scripts being added twice 2024-09-13 15:18:12 -04:00
Shaun Walker
0f2b5531de Merge pull request #4601 from hishamco/module-settings
Add null operator in ModuleState.ModuleDefinition
2024-09-13 14:13:40 -04:00
Hisham Bin Ateya
26e4398905 Address feedback 2024-09-13 21:12:18 +03:00
Shaun Walker
06995f22fe Merge pull request #4609 from sbwalker/dev
improve support for external login roles
2024-09-13 07:35:10 -04:00
sbwalker
caa2073d48 improve support for external login roles 2024-09-13 07:34:57 -04:00
Hisham Bin Ateya
d9466fe4bc Fix issue in toggle edit mode 2024-09-13 14:15:34 +03:00
Shaun Walker
72e623a3a7 Merge pull request #4606 from sbwalker/dev
fix #4598 - user experience improvements for file upload
2024-09-12 14:04:48 -04:00
sbwalker
69bc06685f fix #4598 - user experience improvements for file upload 2024-09-12 14:04:35 -04:00
Mark Davis
bf175984f3 Merge remote-tracking branch 'origin/dev' into dev 2024-09-11 18:23:41 -07:00
Shaun Walker
4d4a7bfd0d Merge pull request #4605 from sbwalker/dev
fix #4600 - filter user settings in API layer
2024-09-11 17:21:24 -04:00
sbwalker
044cee30a5 fix #4600 - filter user settings in API layer 2024-09-11 17:21:12 -04:00
Hisham Bin Ateya
3c0c5aed60 Add null operator in ModuleState.ModuleDefinition 2024-09-11 02:09:02 +03:00
Shaun Walker
e194971727 Merge pull request #4597 from sbwalker/dev
fix #4503 - ensure all state is initialized before rendering
2024-09-09 09:17:40 -04:00
sbwalker
bbe85def23 fix #4503 - ensure all state is initialized before rendering 2024-09-09 09:17:27 -04:00
Shaun Walker
9c2d53f2ae Merge pull request #4596 from sbwalker/dev
fix #4575 - add support for DateOnly and TimeOnly columns in migrations
2024-09-08 11:43:50 -04:00
sbwalker
1cf36e2156 fix #4575 - add support for DateOnly and TimeOnly columns in migrations 2024-09-08 11:43:36 -04:00
Shaun Walker
ce96e309af Merge pull request #4594 from sbwalker/dev
reverting #4507 - permission grid
2024-09-06 11:57:38 -04:00
sbwalker
9ea7dc8b3c reverting #4507 2024-09-06 11:57:15 -04:00
Shaun Walker
282242efd2 Merge pull request #4593 from mdmontesinos/dev
Fix IconOnly not working
2024-09-06 10:47:45 -04:00
David Montesinos
351ba22d64 Fix IconOnly not working 2024-09-06 16:35:44 +02:00
Shaun Walker
2916625747 Merge pull request #4588 from thabaum/patch-8
Update MySQL Project File Version - Prepare for 5.2.2
2024-09-05 10:32:54 -04:00
Cody
744dbeb7a3 Prepare for 5.2.2 2024-09-04 17:43:20 -07:00
Shaun Walker
fbb3c309ee Merge pull request #4583 from sbwalker/dev
prepare for 5.2.2
2024-09-02 12:09:24 -04:00
sbwalker
473c265bac prepare for 5.2.2 2024-09-02 12:09:06 -04:00
Shaun Walker
01b06c2c3c Merge pull request #4582 from sbwalker/dev
remove reference to HttpContext as it is not used
2024-09-02 11:08:38 -04:00
sbwalker
8b1f95c743 remove reference to HttpContext as it is not used 2024-09-02 11:08:25 -04:00
Shaun Walker
ff5dbec579 Merge pull request #4578 from sbwalker/dev
fix issue adding existing user to a new site
2024-08-29 17:53:27 -04:00
sbwalker
9620c5a98f fix issue adding existing user to a new site 2024-08-29 17:53:11 -04:00
Shaun Walker
7e849a2e95 Merge pull request #4577 from zyhfish/task/update-bootstrap-reference 2024-08-29 09:35:32 -04:00
Ben
229aed306e update bootstrap reference. 2024-08-29 19:41:27 +08:00
Shaun Walker
d718969cbd Merge pull request #4574 from zyhfish/task/display-upgrade-progress
display the upgrade progress.
2024-08-28 21:22:08 -04:00
Shaun Walker
8593f4c3a9 Merge pull request #4576 from sbwalker/dev
improve developer experience for Url helper methods
2024-08-28 21:21:57 -04:00
sbwalker
d4f71d5026 improve developer experience for Url helper methods 2024-08-28 21:21:41 -04:00
Shaun Walker
a683a5f206 Merge pull request #4573 from leigh-pointer/AddExisitng
Fix for Deleted Modules showing in AddExisting & CopyExisting dropdow…
2024-08-28 21:17:54 -04:00
Ben
7917cc3eb5 display the upgrade progress. 2024-08-28 21:48:40 +08:00
Leigh Pointer
6cd7ca755e Fix for Deleted Modules showing in AddExisting & CopyExisting dropdown #4572 2024-08-28 10:57:42 +02:00
Shaun Walker
fb7dfdc800 Merge pull request #4571 from sbwalker/dev
provide better support for AllowTextInput on Search component
2024-08-27 12:16:50 -04:00
sbwalker
e096af320f provide better support for AllowTextInput on Search component 2024-08-27 12:16:36 -04:00
Shaun Walker
65bff8f511 Merge pull request #4570 from sbwalker/dev
allow progress indicator to be displayed in search results
2024-08-27 10:22:53 -04:00
sbwalker
ca19d8a842 allow progress indicator to be displayed in search results 2024-08-27 10:22:41 -04:00
Shaun Walker
cde08c64ce Update README.md 2024-08-26 17:00:07 -04:00
Shaun Walker
3d6d7b7cb9 Update README.md 2024-08-26 16:56:08 -04:00
Shaun Walker
a56ef6f398 Update README.md 2024-08-26 16:55:30 -04:00
Shaun Walker
5a38b6614d Update README.md 2024-08-26 16:54:45 -04:00
Shaun Walker
3d5c44e8aa Update README.md 2024-08-26 16:53:25 -04:00
Shaun Walker
46a68bd5e7 Update README.md 2024-08-26 16:51:53 -04:00
Shaun Walker
c77ded51a9 Merge pull request #4568 from sbwalker/dev
fix #4559 - prevednt Log fields from exceeding column length
2024-08-26 12:05:05 -04:00
sbwalker
59bd9fdc22 fix #4559 - prevednt Log fields from exceeding column length 2024-08-26 12:04:50 -04:00
Shaun Walker
b81941394c Merge pull request #4567 from sbwalker/dev
change parameter name to AllowTextInput for clarity
2024-08-26 10:47:29 -04:00
sbwalker
197d5ca1f2 change parameter name to AllowTextInput for clarity 2024-08-26 10:47:18 -04:00
Shaun Walker
97eb986fa6 Merge pull request #4566 from sbwalker/dev
fix Search theme control so that it checks if search is enabled for site, and include AllowInput parameter to control input textbox
2024-08-26 10:41:39 -04:00
sbwalker
aba3110e31 fix Search theme control so that it checks if search is enabled for site, and include AllowInput parameter to control input textbox 2024-08-26 10:41:22 -04:00
Shaun Walker
51c27be236 Merge pull request #4565 from sbwalker/dev
fix #4562 - module template issue caused by gitignore
2024-08-26 09:41:01 -04:00
sbwalker
592255284f fix #4562 - module template issue caused by gitignore 2024-08-26 09:38:10 -04:00
Shaun Walker
82fd41dd4c Merge pull request #4555 from sbwalker/dev
add readme.md to Oqtane nuget packages
2024-08-22 14:10:42 -04:00
sbwalker
4ae8df9652 add readme.md to Oqtane nuget packages 2024-08-22 14:09:59 -04:00
Shaun Walker
759b19e444 Update README.md 2024-08-22 12:23:21 -04:00
Shaun Walker
36f705e46f Update README.md 2024-08-22 12:23:09 -04:00
Shaun Walker
1f0347682e Merge pull request #4553 from oqtane/master
5.2.1 Release
2024-08-22 12:15:38 -04:00
Shaun Walker
1aee385679 Merge pull request #4552 from oqtane/dev
5.2.1 Release
2024-08-22 12:15:15 -04:00
Shaun Walker
5dd8191692 Merge pull request #4551 from sbwalker/dev
fixed required field validation in Search Results Settings
2024-08-22 12:10:34 -04:00
sbwalker
b6422f9b80 fixed required field validation in Search Results Settings 2024-08-22 12:10:15 -04:00
Shaun Walker
a6c2c9c92f Merge pull request #4550 from sbwalker/dev
use localized Yes/No values when displaying Site Urls Default? option
2024-08-22 10:53:43 -04:00
sbwalker
247c573a6e use localized Yes/No values when displaying Site Urls Default? option 2024-08-22 10:53:27 -04:00
Shaun Walker
aa435d6e94 Merge pull request #4548 from sbwalker/dev
fix #4546 - handle cache invalidation for site deletion
2024-08-22 08:26:44 -04:00
sbwalker
f6858c221b fix #4546 - handle cache invalidation for site deletion 2024-08-22 08:26:29 -04:00
Shaun Walker
437aa4510b Merge pull request #4547 from sbwalker/dev
fix #4545 - Site Settings - UI Component Settings changes not refreshed after saving
2024-08-22 08:09:18 -04:00
sbwalker
430572fb32 fix #4545 - Site Settings - UI Component Settings changes not refreshed after saving 2024-08-22 08:08:55 -04:00
Shaun Walker
9f0b755d6f Merge pull request #4543 from sbwalker/dev
fix login redirect issue in sub-site where user has navigated directly to login page
2024-08-21 15:17:47 -04:00
sbwalker
66acb55a57 fix login redirect issue in sub-site where user has navigated directly to login page 2024-08-21 15:17:29 -04:00
Shaun Walker
f936d4c36e Merge pull request #4542 from sbwalker/dev
fix #4536 - deleted modules appearing in Page Management - Modules panel
2024-08-20 16:18:45 -04:00
sbwalker
c3ddb8df56 fix #4536 - deleted modules appearing in Page Management - Modules panel 2024-08-20 16:18:31 -04:00
Shaun Walker
81ce920e69 Merge pull request #4541 from sbwalker/dev
fix issues in default template for Interactive Client (WebAssembly) scenarios
2024-08-20 15:34:05 -04:00
sbwalker
3cb875d139 fix issues in default template for Interactive Client (WebAssembly) scenarios 2024-08-20 15:33:46 -04:00
Shaun Walker
fdb217d5c6 Merge pull request #4540 from sbwalker/dev
set BaseAddress for IHttpClientFactory
2024-08-20 15:22:39 -04:00
sbwalker
085cae3b5f set BaseAddress for IHttpClientFactory 2024-08-20 15:22:27 -04:00
Shaun Walker
e2f99a1554 Merge pull request #4538 from sbwalker/dev
fix #4498 build ServerState Assemblies collection in a more thread safe manner
2024-08-20 14:03:02 -04:00
sbwalker
aee0c27da7 fix #4498 build ServerState Assemblies collection in a more thread safe manner 2024-08-20 14:02:37 -04:00
Shaun Walker
accbf4ad8b Merge pull request #4535 from sbwalker/dev
use existing SiteKey
2024-08-20 08:35:36 -04:00
sbwalker
0ac1901f6b use existing SiteKey 2024-08-20 08:35:23 -04:00
Shaun Walker
c0a0deea78 Merge pull request #4532 from sbwalker/dev
ensure form name is unique in ActionDialog
2024-08-19 16:58:48 -04:00
sbwalker
e3f099441c ensure form name is unique in ActionDialog 2024-08-19 16:58:33 -04:00
Shaun Walker
840dd25cd1 Merge pull request #4530 from sbwalker/dev
fix issues with ActionDialog in static rendering
2024-08-19 09:34:23 -04:00
sbwalker
a493969f9b fix issues with ActionDialog in static rendering 2024-08-19 09:34:08 -04:00
Shaun Walker
cca42a10a1 Merge pull request #4529 from sbwalker/dev
fix CSS
2024-08-19 09:05:00 -04:00
sbwalker
2f4aa98c3c fix CSS 2024-08-19 09:04:46 -04:00
Shaun Walker
175cb9588c Merge pull request #4524 from sbwalker/dev
prevent scroll position from resetting to top of page when querystring or hash changes
2024-08-16 15:01:43 -04:00
sbwalker
a8976e7559 prevent scroll position from resetting to top of page when querystring or hash changes 2024-08-16 15:01:25 -04:00
Shaun Walker
b663528fb0 Merge pull request #4521 from sbwalker/dev
add ability to extract zip file contents in File Management
2024-08-14 15:54:30 -04:00
sbwalker
1a2ad55677 add ability to extract zip file contents in File Management 2024-08-14 15:54:13 -04:00
Shaun Walker
513d2a88c0 Merge pull request #4520 from sbwalker/dev
move HtmlText caching from repository to service layer
2024-08-14 10:01:11 -04:00
sbwalker
57ef4c0396 move HtmlText caching from repository to service layer 2024-08-14 10:00:56 -04:00
Shaun Walker
e9599ca2f4 Merge pull request #4519 from sbwalker/dev
fix #4517 - index error due to duplicate records on upgrade
2024-08-14 08:19:28 -04:00
sbwalker
2fc6dbc222 fix #4517 - index error due to duplicate records on upgrade 2024-08-14 08:19:14 -04:00
Shaun Walker
225933c442 Merge pull request #4518 from sbwalker/dev
update nuspec files for 5.2.1
2024-08-14 08:12:46 -04:00
sbwalker
36e2f048d7 update nuspec files for 5.2.1 2024-08-14 08:12:31 -04:00
Shaun Walker
0e158bce59 Merge pull request #4515 from thabaum/update-version-5.2.1-and-dependencies
Fixes #4514 - Update version 5.2.1 and dependencies
2024-08-14 07:58:55 -04:00
Shaun Walker
202201fd31 Merge pull request #4516 from ijaz-saeed/dev
search settings translation entry
2024-08-14 07:55:11 -04:00
isaeed
4f8c928f44 search settings translation entry 2024-08-14 11:57:06 +05:00
Cody
ada062cf00 Update version to 5.2.1 and dependencies 2024-08-13 15:53:45 -07:00
Cody
32dc12912a Update dependencies 2024-08-13 15:51:49 -07:00
Cody
671d21adf4 Update dependencies 2024-08-13 15:50:56 -07:00
Cody
4e3f8e4b67 Update dependencies 2024-08-13 15:49:15 -07:00
Cody
586bb62073 Update version to 5.2.1 and dependencies 2024-08-13 15:48:32 -07:00
Cody
151bf83ab1 Update version to 5.2.1 and dependencies 2024-08-13 15:46:45 -07:00
Cody
8c618edb5a Update version to 5.2.1 2024-08-13 15:45:23 -07:00
Cody
6d6b0cf8c9 Update version to 5.2.1 and dependencies 2024-08-13 15:44:45 -07:00
Cody
c610608890 Update version to 5.2.1 and dependencies 2024-08-13 15:43:27 -07:00
Cody
28da61daab Update version 5.2.1 and dependencies 2024-08-13 15:39:15 -07:00
Cody
cbfc90f60b Update Version To 5.2.1 and Dependencies To Latest 2024-08-13 15:36:20 -07:00
Shaun Walker
fec92959d4 Merge pull request #4513 from sbwalker/dev
move folder permissions grid to dedicated tab for consistency
2024-08-13 16:48:34 -04:00
sbwalker
bb00d81eba move folder permissions grid to dedicated tab for consistency 2024-08-13 16:48:22 -04:00
Shaun Walker
bb55644c06 Merge pull request #4512 from sbwalker/dev
improve file name and extension validation
2024-08-12 17:02:22 -04:00
sbwalker
16215847cd improve file name and extension validation 2024-08-12 17:02:07 -04:00
Shaun Walker
8ee9aed817 Merge pull request #4509 from sbwalker/dev
improve SettingService
2024-08-12 10:20:56 -04:00
sbwalker
515c6402b9 improve SettingService 2024-08-12 10:20:44 -04:00
Shaun Walker
d1b94ec203 Merge pull request #4507 from leigh-pointer/Permissions-4503
Fix for #4503 Module Custom Permissions not being shown
2024-08-10 17:54:51 -04:00
Leigh Pointer
a037d9167e Fix for #4503 Module Custom Permissions not being shown 2024-08-10 21:25:32 +02:00
Shaun Walker
3054d33e62 Merge pull request #4493 from thabaum/set-samesite-lax-visitor-culture-cookies
Fix #4492: Updates Culture and Visitor cookies to use "Lax" SameSite and Secure Cookie Options
2024-08-10 14:08:01 -04:00
Shaun Walker
6651e641e1 Merge pull request #4505 from sbwalker/dev
add search reindex capability
2024-08-10 10:02:08 -04:00
sbwalker
35f873a342 add search reindex capability 2024-08-10 10:01:52 -04:00
Shaun Walker
2d03ff38a1 Merge pull request #4504 from sbwalker/dev
replace dynamic query with linq
2024-08-09 17:16:30 -04:00
sbwalker
44a3db417b replace dynamic query with linq 2024-08-09 17:16:17 -04:00
Shaun Walker
f9ca702a12 Merge pull request #4502 from sbwalker/dev
fix #4499 - page modules not loaded properly
2024-08-09 13:11:31 -04:00
sbwalker
4073ff38eb fix #4499 - page modules not loaded properly 2024-08-09 13:11:19 -04:00
Shaun Walker
f0e2c9f1b6 Merge pull request #4501 from sbwalker/dev
eliminate database call for authenticated users
2024-08-09 13:00:35 -04:00
sbwalker
cf040f51b5 eliminate database call for authenticated users 2024-08-09 13:00:20 -04:00
Cody
dcf919fb36 Adds AntiForgery Cookie setting options.Cookie.HttpOnly = true; 2024-08-08 12:24:42 -07:00
Shaun Walker
aa19b81a68 Merge pull request #4487 from leigh-pointer/TemplateUpdate
Update Theme Template to Bootstrap 5.3.3
2024-08-08 14:44:27 -04:00
Shaun Walker
db8d77365c Merge pull request #4479 from pollux/patch-1
Fix admin/pages not showing 404 for unauthorized users
2024-08-08 14:42:08 -04:00
Shaun Walker
280eaea84a Merge pull request #4497 from sbwalker/dev
improve search result performance and relevancy
2024-08-08 14:11:43 -04:00
sbwalker
340ef46469 improve search result performance and relevancy 2024-08-08 14:11:27 -04:00
Cody
a5f8651941 Revert previous cookie HttpOnly option 2024-08-07 16:24:18 -07:00
Shaun Walker
8a18ee548e Merge pull request #4494 from sbwalker/dev
add missing indexes
2024-08-07 16:55:48 -04:00
sbwalker
ef791aa22a add missing indexes 2024-08-07 16:55:35 -04:00
Cody
4bdf2e1cc0 Update AntiForgery Token Cookie Option to HTTPOnly = true; 2024-08-07 13:21:18 -07:00
Cody
ffa0ca9379 Updates Culture and Visitor cookies to use "Lax" SameSite and Secure cookie options 2024-08-07 11:52:53 -07:00
Leigh Pointer
d3b3d46fc1 Return to standard Bootstrap 2024-08-07 20:01:41 +02:00
Leigh Pointer
7e7dd8efa9 Update Theme Template to Bootstrap 5.3.3 2024-08-07 10:34:40 +02:00
Shaun Walker
b4506f1133 Merge pull request #4483 from sbwalker/dev
include "://" on default Alias Protocol for consistency
2024-08-05 07:51:07 -04:00
sbwalker
7350c79113 include "://" on default Alias Protocol for consistency 2024-08-05 07:50:54 -04:00
Shaun Walker
5f7b60d3f4 Merge pull request #4480 from leigh-pointer/Log2xHttp
Removed the extra "://" from the Log Manager
2024-08-05 07:50:06 -04:00
Leigh Pointer
266495a611 Removed the extra ";//" from the Log Manager
{alias.Protocol} return with ";//"
2024-08-03 12:26:33 +02:00
lara
f5b4a7e77b Fix admin/pages not showing 404 for unauthorized users 2024-08-02 11:49:55 +02:00
Shaun Walker
51ed0f6487 Merge pull request #4472 from sbwalker/dev
fix #4471 - search pages not being added on upgrade
2024-07-27 09:51:22 -04:00
sbwalker
bd70def18a fix #4471 - search pages not being added on upgrade 2024-07-27 09:51:02 -04:00
Shaun Walker
93a9cf3b31 Update README.md 2024-07-25 13:22:02 -04:00
Shaun Walker
751287999f Update README.md 2024-07-25 11:57:24 -04:00
Shaun Walker
d433850cbf Merge pull request #4469 from oqtane/master
5.2.0 release
2024-07-25 11:49:12 -04:00
Shaun Walker
c93e70e2dc Merge pull request #4468 from oqtane/dev
5.2.0 release
2024-07-25 11:48:50 -04:00
Shaun Walker
a129dd989a Merge pull request #4467 from sbwalker/dev
remove Settings button logic from QuillJS text editor interop
2024-07-25 11:13:19 -04:00
sbwalker
40999c3ff4 remove Settings button logic from QuillJS text editor interop 2024-07-25 11:12:58 -04:00
Shaun Walker
18a01d672c Merge pull request #4466 from sbwalker/dev
resolve localization issue in ActionDialog
2024-07-25 09:24:34 -04:00
sbwalker
3648f99920 resolve localization issue in ActionDialog 2024-07-25 09:24:21 -04:00
Shaun Walker
e823412f56 Merge pull request #4465 from leigh-pointer/NotifyLogging
Small Notification Job update
2024-07-25 08:47:00 -04:00
Leigh Pointer
d090f446c9 Small Notification Job update
This update adds the NotificationId to the log to help track down any errors.
2024-07-25 13:11:05 +02:00
Shaun Walker
19985d1742 Merge pull request #4464 from sbwalker/dev
resolve issue with default Blazor theme
2024-07-24 13:00:03 -04:00
sbwalker
ab52251116 resolve issue with default Blazor theme 2024-07-24 12:59:40 -04:00
Shaun Walker
acb6c0187c Merge pull request #4461 from sbwalker/dev
add missing localization for Search Results Settings
2024-07-23 14:44:30 -04:00
sbwalker
90f9c24720 add missing localization for Search Results Settings 2024-07-23 14:44:14 -04:00
Shaun Walker
415bec4646 Merge pull request #4460 from sbwalker/dev
prevent breaking change for interactive components referencing PageState.Pages
2024-07-23 12:48:13 -04:00
sbwalker
5559f20511 prevent breaking change for interactive components referencing PageState.Pages 2024-07-23 12:47:54 -04:00
Shaun Walker
6ea3399829 Merge pull request #4458 from sbwalker/dev
use PageState.Site.Settings rather than reloading settings from database
2024-07-23 07:45:32 -04:00
sbwalker
9e3df97737 use PageState.Site.Settings rather than reloading settings from database 2024-07-23 07:45:13 -04:00
Shaun Walker
0ac40a4d77 Merge pull request #4456 from leigh-pointer/SixLabors.ImageSharp
ENH update to 3.1.5 #4455 Vulnerabilities detected in 3.1.4
2024-07-23 07:13:45 -04:00
Shaun Walker
24bf5e8102 Merge pull request #4454 from mdmontesinos/dev
fix: set Rich active tab for Quill text editor
2024-07-23 07:13:24 -04:00
Shaun Walker
56eebb03c7 Merge pull request #4457 from sbwalker/dev
change IsEffectiiveOrExpired to IsEffectiveAndNotExpired
2024-07-23 07:11:31 -04:00
sbwalker
1cd4d6d0df change IsEffectiiveOrExpired to IsEffectiveAndNotExpired 2024-07-23 07:08:26 -04:00
Leigh Pointer
22d4a8232a ENH update to 3.1.5 #4455 Vulnerabilities detected in 3.1.4 2024-07-23 13:03:03 +02:00
David Montesinos
48076c25bf fix: set Rich active tab for Quill text editor 2024-07-23 09:18:58 +02:00
Shaun Walker
478a308e73 Merge pull request #4453 from sbwalker/dev
fix #4284 - handle user role effective and expiry date
2024-07-22 21:09:52 -04:00
sbwalker
8ca2f0a49f fix #4284 - handle user role effective and expiry date 2024-07-22 21:09:35 -04:00
Shaun Walker
4a35d7364b Merge pull request #4452 from sbwalker/dev
remove ITextEditorProvider interface
2024-07-22 13:31:39 -04:00
sbwalker
8b2e55a969 remove ITextEditorProvider interface 2024-07-22 13:31:24 -04:00
Shaun Walker
9b14b70687 Merge pull request #4451 from sbwalker/dev
fix #4450 QuillJSTextEditor settings
2024-07-22 08:11:24 -04:00
sbwalker
1c01087eda fix #4450 QuillJSTextEditor settings 2024-07-22 08:11:09 -04:00
Shaun Walker
5137e5a301 Merge pull request #4449 from sbwalker/dev
add documentation
2024-07-21 09:19:00 -04:00
sbwalker
0fea8365b8 add documentation 2024-07-21 09:18:41 -04:00
Shaun Walker
116a615b84 Merge pull request #4448 from sbwalker/dev
change Ignore Paths to Ignore Pages
2024-07-21 09:10:23 -04:00
sbwalker
ef272dd6a8 change Ignore Paths to Ignore Pages 2024-07-21 09:10:01 -04:00
Shaun Walker
4462ae9cae Merge pull request #4447 from sbwalker/dev
moved Search Provider setting to Search Settings
2024-07-21 08:59:41 -04:00
sbwalker
66ffad0b4e moved Search Provider setting to Search Settings 2024-07-21 08:59:23 -04:00
Shaun Walker
81e0fc940c Merge pull request #4446 from sbwalker/dev
add Search Provider to Site Settings
2024-07-21 08:49:38 -04:00
sbwalker
3e8794db1b add Search Provider to Site Settings 2024-07-21 08:49:18 -04:00
Shaun Walker
617622d4d8 Merge pull request #4445 from sbwalker/dev
add Functionality section to Site Settings
2024-07-21 08:16:10 -04:00
sbwalker
a4240f972b add Functionality section to Site Settings 2024-07-21 08:15:51 -04:00
Shaun Walker
42feff8882 Merge pull request #4443 from sbwalker/dev
more localization changes
2024-07-20 21:52:56 -04:00
sbwalker
70edd9686f more localization changes 2024-07-20 21:52:41 -04:00
Shaun Walker
d298cb2e1c Merge pull request #4442 from sbwalker/dev
fix localization for QuillJSTextEditor
2024-07-20 21:43:57 -04:00
sbwalker
3fef3f2dc3 fix localization for QuillJSTextEditor 2024-07-20 21:43:38 -04:00
Shaun Walker
c85f9d6ae4 Merge pull request #4440 from sbwalker/dev
remove unecessary using
2024-07-20 19:39:58 -04:00
sbwalker
85e7ac7cd7 remove unecessary using 2024-07-20 19:39:45 -04:00
Shaun Walker
5c7db61a7e Merge pull request #4439 from sbwalker/dev
improve validation of seach content
2024-07-20 19:18:06 -04:00
sbwalker
497f9ca0b1 improve validation of seach content 2024-07-20 19:17:47 -04:00
Shaun Walker
0c50f7a322 Merge pull request #4438 from sbwalker/dev
allow page-script to support exterrnal JavaScript
2024-07-19 15:42:35 -04:00
sbwalker
740bcbd12c allow page-script to support exterrnal JavaScript 2024-07-19 15:42:20 -04:00
Shaun Walker
c92be4f270 Merge pull request #4437 from sbwalker/dev
revert modification done for testing purposes only
2024-07-19 15:31:24 -04:00
sbwalker
e2a7271ab2 revert modification done for testing purposes only 2024-07-19 15:31:11 -04:00
Shaun Walker
64766713fa Merge pull request #4436 from sbwalker/dev
add ability to manage search results settings
2024-07-19 12:56:14 -04:00
sbwalker
59bba83b1d add ability to manage search results settings 2024-07-19 12:55:59 -04:00
Shaun Walker
8ac1217165 Merge pull request #4435 from sbwalker/dev
allow <style> tags to be injected using HeadContent
2024-07-18 15:01:43 -04:00
sbwalker
5443629ec5 allow <style> tags to be injected using HeadContent 2024-07-18 15:01:20 -04:00
Shaun Walker
8f9b41cb62 Merge pull request #4434 from sbwalker/dev
use JSInterop for loading QuillJSTextEditor stylesheet
2024-07-18 13:17:58 -04:00
sbwalker
7df5eba775 use JSInterop for loading QuillJSTextEditor stylesheet 2024-07-18 13:17:23 -04:00
Shaun Walker
e29c6ac593 Merge pull request #4433 from sbwalker/dev
improve search user experience
2024-07-18 11:50:07 -04:00
sbwalker
4f3190bf73 improve search user experience 2024-07-18 11:49:42 -04:00
Shaun Walker
f0878fccb5 Merge pull request #4432 from sbwalker/dev
fix ISearchable implementation in default module template
2024-07-18 11:10:39 -04:00
sbwalker
b0e121a53f fix ISearchable implementation in default module template 2024-07-18 11:10:24 -04:00
Shaun Walker
eda48ab0e6 Merge pull request #4431 from sbwalker/dev
QuillJSTextEditor setting improvements
2024-07-18 11:03:13 -04:00
sbwalker
6a1014d8c1 QuillJSTextEditor setting improvements 2024-07-18 11:01:01 -04:00
Shaun Walker
e0f87315bc Merge pull request #4430 from sbwalker/dev
set Prerender on Login component
2024-07-17 20:52:28 -04:00
sbwalker
f2c5dca5e7 set Prerender on Login component 2024-07-17 20:52:13 -04:00
Shaun Walker
3c435a804f Merge pull request #4429 from sbwalker/dev
remove hardcoded names when using GetInterface()
2024-07-17 19:53:06 -04:00
sbwalker
7ee6775251 remove hardcoded names when using GetInterface() 2024-07-17 19:52:44 -04:00
Shaun Walker
98adc2ecc1 Merge pull request #4428 from sbwalker/dev
allow search content permissions to support roles
2024-07-17 19:34:34 -04:00
sbwalker
45afbbdac6 allow search content permissions to support roles 2024-07-17 19:34:19 -04:00
Shaun Walker
a18260747b Merge pull request #4427 from sbwalker/dev
add Refresh option for Job Logs
2024-07-17 17:12:38 -04:00
sbwalker
0c80e28754 add Refresh option for Job Logs 2024-07-17 17:12:24 -04:00
Shaun Walker
719bc374ac Merge pull request #4426 from sbwalker/dev
add localization to search settings
2024-07-17 16:34:16 -04:00
sbwalker
d7a290c595 add localization to search settings 2024-07-17 16:34:02 -04:00
Shaun Walker
4b2bd33baa Merge pull request #4425 from sbwalker/dev
update theme template to .NET 8.0.7
2024-07-17 16:23:30 -04:00
sbwalker
efbe4d697c update theme template to .NET 8.0.7 2024-07-17 16:23:15 -04:00
Shaun Walker
a8662bdb8b Merge pull request #4424 from sbwalker/dev
use Task.FromResult()
2024-07-17 16:22:16 -04:00
sbwalker
d822225465 use Task.FromResult() 2024-07-17 16:22:01 -04:00
Shaun Walker
c6373ef582 Merge pull request #4423 from sbwalker/dev
update module template to .NET 8.0.7
2024-07-17 16:17:30 -04:00
sbwalker
5a2af6d0f9 update module template to .NET 8.0.7 2024-07-17 16:17:10 -04:00
Shaun Walker
52000d6a41 Merge pull request #4422 from sbwalker/dev
update to .NET 8.0.7
2024-07-17 15:10:54 -04:00
sbwalker
befa13eaf2 update to .NET 8.0.7 2024-07-17 15:10:40 -04:00
Shaun Walker
4ac68a81a3 Merge pull request #4421 from sbwalker/dev
search optimizations
2024-07-17 13:58:03 -04:00
sbwalker
71e472f330 search optimizations 2024-07-17 13:57:47 -04:00
Shaun Walker
ada8809ec0 Merge pull request #4420 from oqtane/revert-4417-dev
Revert "disable prerendering by default for static rendered sites"
2024-07-17 12:13:35 -04:00
Shaun Walker
25ea518266 Revert "revert #4250 which disabled prerendering by default for static rendered sites" 2024-07-17 12:12:58 -04:00
Shaun Walker
f3720c3b94 Merge pull request #4419 from sbwalker/dev
improve PageState trimming
2024-07-17 11:53:22 -04:00
sbwalker
b942a84b15 improve PageState trimming 2024-07-17 11:53:04 -04:00
Shaun Walker
574ca90229 Merge pull request #4418 from sbwalker/dev
add missing properties to Clone method
2024-07-17 11:34:15 -04:00
sbwalker
5610a14e49 add missing properties to Clone method 2024-07-17 11:34:01 -04:00
Shaun Walker
c5bc62e6df Merge pull request #4417 from sbwalker/dev
revert #4250 which disabled prerendering by default for static rendered sites
2024-07-17 11:22:18 -04:00
sbwalker
e9f6a85cad revert #4250 which disabled prerendering by default for static rendered sites 2024-07-17 11:20:27 -04:00
Shaun Walker
8921011b27 Merge pull request #4416 from sbwalker/dev
performance improvement in Control Panel to only load list of pages when necessary
2024-07-17 11:13:46 -04:00
sbwalker
90ef3f6c94 performance improvement in Control Panel to only load list of pages when necessary 2024-07-17 11:13:27 -04:00
Shaun Walker
e84c75f4a8 Merge pull request #4414 from pollux/patch-1
Update Oqtane.Shared.csproj
2024-07-17 11:09:59 -04:00
Shaun Walker
68e20cd860 Merge pull request #4415 from sbwalker/dev
include Search Settings
2024-07-17 11:09:00 -04:00
sbwalker
76bdcea4b1 include Search Settings 2024-07-17 11:08:43 -04:00
lara
f758cb7e6e Update Oqtane.Shared.csproj
Fixes CVE-2024-30105
2024-07-17 12:46:49 +02:00
Shaun Walker
1108477810 Merge pull request #4413 from sbwalker/dev
make SearchResults API consistent with other core APIs
2024-07-16 16:55:09 -04:00
sbwalker
deb6a9e51c make SearchResults API consistent with other core APIs 2024-07-16 16:54:55 -04:00
Shaun Walker
9660f20b87 Merge pull request #4412 from sbwalker/dev
performance optimization to mitigate page bloat caused by Blazor serializing/encrypting state when crossing render mode boundaries
2024-07-16 16:21:57 -04:00
sbwalker
4d26468ede performance optimization to mitigate page bloat caused by Blazor serializing/encrypting state when crossing render mode boundaries 2024-07-16 16:21:35 -04:00
Shaun Walker
125a0979d5 Merge pull request #4408 from sbwalker/dev
removed unused constants
2024-07-15 10:11:31 -04:00
sbwalker
98bdfd3dbe removed unused constants 2024-07-15 10:11:14 -04:00
Shaun Walker
ea72880e74 Merge pull request #4407 from sbwalker/dev
resolve security issue in Search
2024-07-15 10:08:04 -04:00
sbwalker
17fec7d6e1 resolve security issue in Search 2024-07-15 10:07:48 -04:00
Shaun Walker
d9de64604e Merge pull request #4406 from sbwalker/dev
fix #4401 - avoid mutating Site object in cache
2024-07-15 08:37:46 -04:00
sbwalker
6275ab23ff fix #4401 - avoid mutating Site object in cache 2024-07-15 08:37:23 -04:00
Shaun Walker
8c0271643d Merge pull request #4405 from sbwalker/dev
testing search indexing of files
2024-07-13 09:28:25 -04:00
sbwalker
c3f041dc87 testing search indexing of files 2024-07-13 09:28:02 -04:00
Shaun Walker
80e5e84341 Merge pull request #4404 from sbwalker/dev
only include pages in index if they do not have any modules
2024-07-12 10:53:25 -04:00
sbwalker
938eee80a9 only include pages in index if they do not have any modules 2024-07-12 10:52:58 -04:00
Shaun Walker
7abc2289de Merge pull request #4402 from sbwalker/dev
search modifications
2024-07-12 10:33:34 -04:00
sbwalker
bb79b9ed74 search modifications 2024-07-12 10:33:17 -04:00
Shaun Walker
1e89a8625c Merge pull request #4400 from sbwalker/dev
fix #4397 - remove incorrect help text
2024-07-11 13:39:19 -04:00
sbwalker
90b0f04b3c fix #4397 - remove incorrect help text 2024-07-11 13:39:05 -04:00
Shaun Walker
0f019cd9b6 Merge pull request #4399 from sbwalker/dev
fix #4398 - InputList component not handling scenario where input is reset to nothing
2024-07-11 13:36:14 -04:00
sbwalker
1209739398 fix #4398 - InputList component not handling scenario where input is reset to nothing 2024-07-11 13:35:46 -04:00
Shaun Walker
b99db2b353 Merge pull request #4394 from sbwalker/dev
more Site Settings for search configuration
2024-07-08 16:59:10 -04:00
sbwalker
f057688e7d more Site Settings for search configuration 2024-07-08 16:58:55 -04:00
Shaun Walker
12ae2d0c76 Merge pull request #4393 from sbwalker/dev
site settings to configure indexing
2024-07-08 14:33:54 -04:00
sbwalker
9d91d5a127 site settings to configure indexing 2024-07-08 14:33:16 -04:00
Shaun Walker
6015f0887a Merge pull request #4389 from sbwalker/dev
fix #4384 - app_offline https link
2024-07-06 08:38:52 -04:00
sbwalker
d4c473d7b3 fix #4384 - app_offline https link 2024-07-06 08:38:33 -04:00
Shaun Walker
2f3978deed Merge pull request #4374 from zyhfish/task/fix-issue-4358
Fix #4358: RichTextEditor Provider Abstraction.
2024-07-06 08:32:19 -04:00
Shaun Walker
34af53a15b Merge branch 'dev' into task/fix-issue-4358 2024-07-06 08:32:10 -04:00
Shaun Walker
a4eb3d7a0b Merge pull request #4388 from sbwalker/dev
search refactoring
2024-07-06 07:58:35 -04:00
sbwalker
5b46dd7293 search refactoring 2024-07-06 07:58:04 -04:00
Mark Davis
4b17847ea5 Merge remote-tracking branch 'oqtane/dev' into dev 2024-07-05 21:53:14 -07:00
Ben
acbe000f97 avoid race condition issue. 2024-07-03 17:59:40 +08:00
Ben
599071b68b avoid race condition issue. 2024-07-03 17:07:47 +08:00
Ben
2bacee919d update the settings UI. 2024-07-03 12:26:36 +08:00
Shaun Walker
50d35e4196 Merge pull request #4383 from sbwalker/dev
remove unnecessary using
2024-07-02 15:53:40 -04:00
sbwalker
e321998b85 remove unnecessary using 2024-07-02 15:53:26 -04:00
Shaun Walker
340c02b2af Merge pull request #4382 from sbwalker/dev
remove unnecessary database call to GetPage
2024-07-02 15:45:59 -04:00
sbwalker
69a295fe57 remove unnecessary database call to GetPage 2024-07-02 15:45:44 -04:00
Shaun Walker
64830aae9f Merge pull request #4381 from sbwalker/dev
use PageModule in ISearchable
2024-07-02 14:50:42 -04:00
sbwalker
8969b1273f use PageModule in ISearchable 2024-07-02 14:50:26 -04:00
Shaun Walker
475faf7943 Merge pull request #4380 from sbwalker/dev
fix #4375 - deleted pages not being filtered
2024-07-02 11:05:42 -04:00
sbwalker
45b1d405a6 fix #4375 - deleted pages not being filtered 2024-07-02 11:05:29 -04:00
Ben
f60c8078e4 cleanup the code. 2024-07-02 09:55:38 +08:00
Ben
6701e49f9a move the editor settings into editor self control. 2024-07-02 09:50:53 +08:00
Shaun Walker
0efb3c3284 Merge pull request #4376 from sbwalker/dev
ensure UniqueKey is unique by including TenantId and SiteId
2024-07-01 16:20:15 -04:00
sbwalker
aaf3cdfdac ensure UniqueKey is unique by including TenantId and SiteId 2024-07-01 16:19:58 -04:00
Ben
e00c261777 Fix #4358: RichTextEditor Provider Abstraction. 2024-07-01 17:11:26 +08:00
Shaun Walker
1eafed755d Merge pull request #4372 from sbwalker/dev
provide default Permissions value
2024-06-28 17:31:48 -04:00
sbwalker
7f6a08ae50 provide default Permissions value 2024-06-28 17:31:33 -04:00
Shaun Walker
9901816fb9 Merge pull request #4371 from sbwalker/dev
ensure ModuleDefinition exists
2024-06-28 17:26:58 -04:00
sbwalker
3cbe6c1e95 ensure ModuleDefinition exists 2024-06-28 17:26:46 -04:00
Shaun Walker
679c99274e Merge pull request #4370 from sbwalker/dev
change EntityId to string
2024-06-28 16:25:11 -04:00
sbwalker
b6fa0f1ff6 change EntityId to string 2024-06-28 16:24:56 -04:00
Shaun Walker
9ff64b95e1 Merge pull request #4369 from sbwalker/dev
modify query property names
2024-06-28 16:15:42 -04:00
sbwalker
3a9885abd8 modify query property names 2024-06-28 16:15:28 -04:00
Shaun Walker
503210942c Merge pull request #4368 from sbwalker/dev
breaking search modifications into smaller PRs
2024-06-28 15:44:11 -04:00
sbwalker
0178e015e3 breaking search modifications into smaller PRs 2024-06-28 15:43:54 -04:00
Shaun Walker
7604992c35 Merge pull request #4361 from 2sic-forks/bug/4360
fix docfx build issues #4360
2024-06-28 09:01:45 -04:00
Shaun Walker
ee9e551788 Merge pull request #4365 from sbwalker/dev
reposition Search input in themes
2024-06-27 17:18:54 -04:00
sbwalker
22063248ca reposition Search input in themes 2024-06-27 17:18:41 -04:00
Shaun Walker
e4ce18b35c Merge pull request #4364 from sbwalker/dev
eager load Page associated to PageModule
2024-06-27 17:05:35 -04:00
sbwalker
532890674e eager load Page associated to PageModule 2024-06-27 17:05:22 -04:00
iJungleboy
791a3b67e6 fix docfx build issues 2024-06-27 19:47:13 +02:00
Shaun Walker
84b560ef29 Merge pull request #4356 from sbwalker/dev
fix #4353 - add defensive logic when sending notifications and improve performance
2024-06-26 09:09:29 -04:00
sbwalker
03f081f3f4 fix #4353 - add defensive logic when sending notifications and improve performance 2024-06-26 09:09:06 -04:00
Shaun Walker
08213ae86e Merge pull request #4352 from sbwalker/dev
fix #4349 - adding module in subsite in Interactive render mode
2024-06-24 16:27:35 -04:00
sbwalker
73abc511a8 fix #4349 - adding module in subsite in Interactive render mode 2024-06-24 16:26:55 -04:00
Shaun Walker
1c943cc259 Merge pull request #4350 from sbwalker/dev
fix #4339 - add page not redirecting to correct url in subsite
2024-06-24 11:00:01 -04:00
sbwalker
af62a89a6b fix #4339 - add page not redirecting to correct url in subsite 2024-06-24 10:59:34 -04:00
Shaun Walker
af7ca5b897 Merge pull request #4338 from sbwalker/dev
use List instead of IList, remove "List" from method names. remove unnecessary using statements
2024-06-11 10:39:03 -04:00
sbwalker
27356ef747 use List instead of IList, remove "List" from method names. remove unnecessary using statements 2024-06-11 10:38:44 -04:00
Shaun Walker
b27f80ef87 Merge pull request #4337 from leigh-pointer/SearchResultsCat
Updated SearchResults Categories to Admin
2024-06-11 10:28:56 -04:00
Leigh Pointer
b4aa73fc64 Updated SearchResults Categories to Admin 2024-06-11 15:21:12 +02:00
Shaun Walker
bbf444572b Merge pull request #4336 from sbwalker/dev
removed IHttpContextAccessor as it shoudl not be used in Blazor,  fixed form handling, added Reset button to consistent with other framework search options, used SharedLocalizer, removed unused localization keys
2024-06-11 08:39:28 -04:00
sbwalker
b3706574de removed IHttpContextAccessor as it shoudl not be used in Blazor, fixed form handling, added Reset button to consistent with other framework search options, used SharedLocalizer, removed unused localization keys 2024-06-11 08:38:51 -04:00
Shaun Walker
83062f8bfb Merge pull request #4335 from sbwalker/dev
fix ISearchable method name in module template
2024-06-11 07:37:25 -04:00
sbwalker
1d7fcfdaa1 fix ISearchable method name in module template 2024-06-11 07:37:02 -04:00
Shaun Walker
58ab12b4cb Merge pull request #4328 from leigh-pointer/UpdateTemplates
Update Project Templates from 8.0.5 - 8.0.6
2024-06-11 07:35:02 -04:00
Shaun Walker
28c649629f Merge pull request #4334 from leigh-pointer/Bootstrap5.3.3
Upgrade to Bootstrap 5.3.3
2024-06-11 07:32:10 -04:00
Leigh Pointer
5ec190225d Upgrade to Bootstrap 5.3.3
Oqtane ThemeInfo updated
Blazor Default.razor updated
2024-06-11 09:51:48 +02:00
Leigh Pointer
0e0d404997 Update [Module]Manager.cs 2024-06-11 09:11:25 +02:00
Leigh Pointer
3f16b908ca Merge remote-tracking branch 'upstream/dev' into UpdateTemplates 2024-06-11 08:49:28 +02:00
Shaun Walker
54549b261c Merge pull request #4333 from sbwalker/dev
change IList to List for consistency with rest of framework
2024-06-10 17:17:33 -04:00
sbwalker
8ce07ced9e change IList to List for consistency with rest of framework 2024-06-10 17:17:20 -04:00
Shaun Walker
37a5144e8f Merge pull request #4332 from sbwalker/dev
update app constant to 5.2.0
2024-06-10 16:50:45 -04:00
sbwalker
59fed7dda8 update app constant to 5.2.0 2024-06-10 16:50:33 -04:00
Shaun Walker
0a85a2868c Merge pull request #4331 from sbwalker/dev
fix issue with primary key on SearchContentWord table
2024-06-10 16:47:45 -04:00
sbwalker
0d493b3250 fix issue with primary key on SearchContentWord table 2024-06-10 16:47:32 -04:00
Shaun Walker
74530d4b1e Merge pull request #4330 from sbwalker/dev
remove unnecessary using statements
2024-06-10 16:23:10 -04:00
sbwalker
7548c52e21 remove unnecessary using statements 2024-06-10 16:22:58 -04:00
Shaun Walker
fa49844c64 Merge pull request #4329 from sbwalker/dev
remove List from method name to conform to Oqtane naming conventions
2024-06-10 16:17:19 -04:00
sbwalker
3508ae1e0a remove List from method name to conform to Oqtane naming conventions 2024-06-10 16:17:05 -04:00
Leigh Pointer
f013ee64a2 Updated Module Template with ISearchable implementation 2024-06-10 22:10:39 +02:00
Leigh Pointer
af3da7ca6e update to template.json files to align with Oqtane version 2024-06-10 21:54:44 +02:00
Leigh Pointer
cb728f65b3 Update Project Templates from 8.0.5 - 8.0.6 2024-06-10 21:50:30 +02:00
Shaun Walker
af6af190cc Merge pull request #4325 from thabaum/update-package-dependences-v5.2.0
Fixes #4324: Updates package dependences and prepares v5.2.0 release
2024-06-10 15:06:08 -04:00
Shaun Walker
cbcc8455ca Merge pull request #4326 from sbwalker/dev
refactored to move AdminSiteTemplate out of SiteRepository
2024-06-10 14:55:21 -04:00
sbwalker
af35fb79fe refactored to move AdminSiteTemplate out of SiteRepository 2024-06-10 14:55:06 -04:00
Cody
0515aaa946 Prepare v5.2.0 Release 2024-06-10 10:48:46 -07:00
Cody
1d00330e7a Prepare v5.2.0 Release and Package Dependencies 2024-06-10 10:48:18 -07:00
Cody
3fa6dcea16 Prepare v5.2.0 Release and Package Dependencies 2024-06-10 10:47:03 -07:00
Cody
51425cac4a Prepare v5.2.0 Release 2024-06-10 10:44:40 -07:00
Cody
7ce61a5d2b Prepare v5.2.0 Release 2024-06-10 10:43:54 -07:00
Cody
5e5caa979b Prepare v5.2.0 Release 2024-06-10 10:43:19 -07:00
Cody
a719518f8f Prepare v5.2.0 Release 2024-06-10 10:42:57 -07:00
Cody
d0e5aef443 Prepare v5.2.0 Release 2024-06-10 10:42:32 -07:00
Cody
b82a811c33 Prepare v5.2.0 Release and Package Dependencies 2024-06-10 10:41:51 -07:00
Cody
3356dcf8f7 Prepare v5.2.0 Release 2024-06-10 10:41:10 -07:00
Cody
8f1cc26537 Prepare v5.2.0 Release 2024-06-10 10:40:50 -07:00
Cody
27dafa83ac Prepare Update v5.2.0 Package Dependencies 2024-06-10 10:38:52 -07:00
Cody
c1be1f329f Prepare Update v5.2.0 Package Dependencies 2024-06-10 10:37:51 -07:00
Cody
c757cef549 Prepare Update v5.2.0 Package Dependencies 2024-06-10 10:37:21 -07:00
Cody
da9e4c026c Prepare Update v5.2.0 Package Dependencies 2024-06-10 10:37:04 -07:00
Cody
5821d67e69 Prepare Update v5.2.0 Package Dependencies 2024-06-10 10:36:47 -07:00
Cody
ed14f6d13f Prepare Update v5.2.0 Package Dependencies 2024-06-10 10:35:43 -07:00
Cody
35bdd8b4ef Prepare Update v5.2.0 Package Dependencies 2024-06-10 10:35:16 -07:00
Cody
9cf2d30e77 Prepare Update v5.2.0 2024-06-10 10:32:30 -07:00
Cody
a2140a3b7b Update v5.2.0 Package Dependencies 2024-06-10 10:30:37 -07:00
Cody
900d026bcb Update v5.2.0 Package Dependencies 2024-06-10 10:29:58 -07:00
Cody
68604ec15a Update Oqtane.Database.PostgreSQL.csproj Package Dependencies 2024-06-10 10:28:51 -07:00
Cody
f7c0ebb8d3 Update Oqtane.Database.MySQL.csproj prepare 5.2.0 2024-06-10 10:27:53 -07:00
Cody
8be5d0c72d Update Oqtane.Database.MySQL.csproj Package Dependencies 2024-06-10 10:27:15 -07:00
Cody
15c8b724e6 Update Oqtane.Client.csproj Package Dependencies 2024-06-10 10:24:52 -07:00
Shaun Walker
d6949200f9 Merge pull request #4323 from sbwalker/dev
move Search page/module to Admin template so that it is always provisioned
2024-06-10 12:33:31 -04:00
sbwalker
1c2abe794a move Search page/module to Admin template so that it is always provisioned 2024-06-10 12:33:09 -04:00
Shaun Walker
0bcf393586 Merge pull request #4320 from sbwalker/dev
search refactoring
2024-06-08 16:24:32 -04:00
sbwalker
bc0573918f search refactoring 2024-06-08 16:14:56 -04:00
Shaun Walker
175675ad99 Merge pull request #4317 from zyhfish/task/fix-issue-4316
Fix #4316: add text editor interfaces.
2024-06-07 14:44:40 -04:00
Ben
b00c2afc46 Fix #4316: move the raw html editor into quill editor instance. 2024-06-07 08:35:42 +08:00
Ben
c125a7fe07 Fix #4316: add text editor interfaces. 2024-06-06 16:39:35 +08:00
Shaun Walker
a42ab32436 Merge pull request #4310 from zyhfish/task/fix-searchbox-responsive-issue
Fix #4309: make searchbox responsive.
2024-06-05 07:48:55 -04:00
Shaun Walker
797a64976e Merge pull request #4311 from fonsecaf/fix-cookie-date-culture-format
Fix Cookie Date Conversion to Respect Culture and Format
2024-06-05 07:48:43 -04:00
fonsecaf
ac377a8b68 Modified date parsing and formatting to use invariant culture, ensuring consistency and preventing non-ASCII characters in HTTP headers. 2024-06-05 13:39:31 +10:00
Ben
842b7b1402 Fix #4309: make searchbox responsive. 2024-06-05 10:27:38 +08:00
Shaun Walker
d449396ad5 Merge pull request #4304 from zyhfish/task/add-search-function
#4303: add search function.
2024-06-04 16:52:10 -04:00
Shaun Walker
532a87d064 Merge pull request #4307 from leigh-pointer/OqtaneControls
Oqtane controls updates
2024-06-04 16:50:53 -04:00
Ben
e1cdc7b387 return the words count to calculate the ranking. 2024-06-04 21:57:50 +08:00
Ben
d9d917e267 set search result page path to be parameter. 2024-06-04 21:09:25 +08:00
Leigh Pointer
8048788042 Oqtane controls updates
ActionDialog and ActionLink now allow other icon sets whilst still adhering to the legacy "oi oi-" icon set.
Pager added SearchBoxClass Class parameter to the Search div.
TabStrip added a TabContentClass Class parameter to the tab content div.
2024-06-04 12:21:59 +02:00
Ben
790fc88e47 using correct module id value. 2024-06-04 17:50:29 +08:00
Ben
7f970d489f refactoring the code. 2024-06-04 17:32:31 +08:00
Ben
9d85ca07f4 #4303: add search function. 2024-06-03 21:19:42 +08:00
Shaun Walker
d75e3acdf3 Merge pull request #4302 from sbwalker/dev
changes as a result of #4299 related to  PageState.Modules
2024-06-03 07:42:46 -04:00
sbwalker
694cda0e99 changes as a result of #4299 related to PageState.Modules 2024-06-03 07:42:22 -04:00
Shaun Walker
94f134c6a7 Merge pull request #4301 from zyhfish/task/fix-add-page-issue
Fix Add Page Issue
2024-06-01 09:04:28 -04:00
Ben
83f329d93c Fix Add Page Issue 2024-06-01 09:08:43 +08:00
Shaun Walker
de49387fca Merge pull request #4300 from sbwalker/dev
remove LoadTestingSiteTemplate
2024-05-31 16:51:45 -04:00
sbwalker
e5567f2f46 remove LoadTestingSiteTemplate 2024-05-31 16:51:27 -04:00
Shaun Walker
80f545f3d5 Merge pull request #4299 from sbwalker/dev
scalability improvements
2024-05-31 16:23:50 -04:00
sbwalker
06f0cc70b8 scalability improvements 2024-05-31 16:23:36 -04:00
Shaun Walker
cf6b7544b0 Update README.md 2024-05-28 15:20:37 -04:00
Shaun Walker
d511c6334a Update README.md 2024-05-28 15:20:15 -04:00
Shaun Walker
0224fd6d54 Update README.md 2024-05-28 15:17:27 -04:00
Mark Davis
2addcc3ab5 Merge branch 'dev' of https://github.com/Trifoia/oqtane.framework into dev 2024-03-28 13:47:43 -07:00
markdav-is
370b39a139 Merge branch 'release/v5.0.1' into dev 2024-01-27 21:18:58 -08:00
Mark Davis
7b7e64576f Update appsettings.json 2024-01-27 20:30:20 -08:00
Mark Davis
286928d59e Merge tag 'v5.0.1' into dev 2023-12-29 11:54:39 -08:00
Mark Davis
cc65555c3d minor fix to routing 2023-12-05 12:17:02 -08:00
Mark Davis
63e3923349 Merge remote-tracking branch 'oqtane/dev' into dev 2023-11-17 12:55:40 -08:00
687 changed files with 29920 additions and 11370 deletions

View File

@@ -1,2 +0,0 @@
[config]
project = Oqtane.Server/Oqtane.Server.csproj

11
.gitignore vendored
View File

@@ -22,10 +22,17 @@ Oqtane.Server/Packages
Oqtane.Server/wwwroot/Content
Oqtane.Server/wwwroot/Packages/*.log
Oqtane.Server/wwwroot/Modules
Oqtane.Server/wwwroot/_content/*
!Oqtane.Server/wwwroot/_content/Placeholder.txt
Oqtane.Server/wwwroot/Modules/*
!Oqtane.Server/wwwroot/Modules/Oqtane.Modules.*
!Oqtane.Server/wwwroot/Modules/Templates
Oqtane.Server/wwwroot/Modules/Templates/*
!Oqtane.Server/wwwroot/Modules/Templates/External
Oqtane.Server/wwwroot/Themes
Oqtane.Server/wwwroot/Themes/*
!Oqtane.Server/wwwroot/Themes/Oqtane.Themes.*
!Oqtane.Server/wwwroot/Themes/Templates
Oqtane.Server/wwwroot/Themes/Templates/*
!Oqtane.Server/wwwroot/Themes/Templates/External

24
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,24 @@
# Contributing to Oqtane
## How to Contribute
We track all of our issues on Github. If you want to contribute, everything starts with an issue. If you don't have an issue yet, you can add one. Then a core contributor will tag it as either an enhancement [ENH] or a bug [BUG]. Tagged issues are open for contribution.
## Use GitHub-flow process
- Make a comment on the issue that you intend to work on it and read all the comments to gain a full understanding.
- Fork the repository
- Create a new branch and update your comment on the issue with a llink to the branch
- Make your changes and commit them
- Push to the branch
- Create a pull request
## Reporting Bugs
- Check if the issue has already been reported.
- Open a new issue if it hasnt been reported.
## Requesting Features
- Use the feature request template in the Issues tab.
Thank you for contributing!

17
Directory.Build.props Normal file
View File

@@ -0,0 +1,17 @@
<Project>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Configurations>Debug;Release</Configurations>
<Version>10.0.3</Version>
<Product>Oqtane</Product>
<Authors>Shaun Walker</Authors>
<Company>.NET Foundation</Company>
<Description>CMS and Application Framework for Blazor and .NET MAUI</Description>
<Copyright>.NET Foundation</Copyright>
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v10.0.3</PackageReleaseNotes>
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
</PropertyGroup>
</Project>

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018-2024 .NET Foundation
Copyright (c) 2018-2025 .NET Foundation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

9
Oqtane.Application/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
.vs/
bin/
obj/
*.user
artifacts/
msbuild.binlog
.vscode/
*.binlog
*.nupkg

View File

@@ -0,0 +1,81 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "Shaun Walker",
"classifications": [
"Web",
"ASP.NET",
"Blazor",
"Oqtane"
],
"name": "Oqtane Application Template",
"shortName": "oqtane-app",
"defaultName": "MyCompany.MyProject",
"identity": "Oqtane.Application.Template",
"tags": {
"language": "C#",
"type": "solution",
"editorTreatAs":"solution"
},
"sourceName": "Oqtane.Application",
"preferNameDirectory": true,
"symbols": {
"Framework": {
"type": "parameter",
"description": "The target framework for the project",
"datatype": "choice",
"choices": [
{
"choice": "net10.0",
"description": "Target net10.0"
}
],
"replaces": "net10.0",
"defaultValue": "net10.0"
},
"HttpPort": {
"type": "parameter",
"datatype": "integer",
"description": "Port number to use for the HTTP endpoint in launchSettings.json."
},
"HttpPortGenerated": {
"type": "generated",
"generator": "port"
},
"HttpPortReplacer": {
"type": "generated",
"generator": "coalesce",
"parameters": {
"sourceVariableName": "HttpPort",
"fallbackVariableName": "HttpPortGenerated"
},
"replaces": "44358"
},
"HttpsPort": {
"type": "parameter",
"datatype": "integer",
"description": "Port number to use for the HTTPS endpoint in launchSettings.json."
},
"HttpsPortGenerated": {
"type": "generated",
"generator": "port",
"parameters": {
"low": 44300,
"high": 44399
}
},
"HttpsPortReplacer": {
"type": "generated",
"generator": "coalesce",
"parameters": {
"sourceVariableName": "HttpsPort",
"fallbackVariableName": "HttpsPortGenerated"
},
"replaces": "44359"
}
},
"primaryOutputs": [
{
"path": "Oqtane.Application.slnx"
}
]
}

View File

@@ -0,0 +1,3 @@
using Microsoft.Extensions.Localization;
[assembly: RootNamespace("Oqtane.Application.Client")]

View File

@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Version>1.0.0</Version>
<AssemblyName>Oqtane.Application.Client.Oqtane</AssemblyName>
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
<PublishTrimmed>false</PublishTrimmed>
<BlazorEnableCompression>false</BlazorEnableCompression>
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\Oqtane.Application.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Oqtane.Client" Version="10.0.3" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,13 @@
using System.Threading.Tasks;
namespace Oqtane.Application.Client
{
internal class Program
{
static async Task Main(string[] args)
{
// defer client startup to Oqtane - do not modify
await Oqtane.Client.Program.Main(args);
}
}
}

View File

@@ -0,0 +1,25 @@
@using System
@using System.Linq
@using System.Collections.Generic
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.Extensions.Localization
@using Microsoft.JSInterop
@using Oqtane
@using Oqtane.Models
@using Oqtane.Modules
@using Oqtane.Modules.Controls
@using Oqtane.Providers
@using Oqtane.Security
@using Oqtane.Services
@using Oqtane.Shared
@using Oqtane.Themes
@using Oqtane.Themes.Controls
@using Oqtane.UI
@using Oqtane.Enums
@using Oqtane.Interfaces

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Oqtane.Application.Template</id>
<version>10.0.3</version>
<title>Oqtane Application Template For Blazor</title>
<authors>Shaun Walker</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<license type="expression">MIT</license>
<licenseUrl>https://licenses.nuget.org/MIT</licenseUrl>
<icon>icon.png</icon>
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
<description>Oqtane is an open source CMS and Application Framework that provides advanced functionality for developing web, mobile, and desktop applications on .NET. It leverages Blazor to compose a fully dynamic digital experience which can be hosted on Static Blazor, Blazor Server, Blazor WebAssembly, or Blazor Hybrid (via .NET MAUI).</description>
<language>en-US</language>
<tags>Web ASP.NET Blazor Oqtane Modular Multi-Tenant "Open Source" "SQL Server" MySQL PostgreSQL SQLite</tags>
<readme>README.md</readme>
<packageTypes>
<packageType name="Template" />
</packageTypes>
</metadata>
</package>

View File

@@ -0,0 +1,5 @@
<Solution>
<Project Path="Server\Oqtane.Application.Server.csproj" DefaultStartup="true" />
<Project Path="Client\Oqtane.Application.Client.csproj" />
<Project Path="Shared\Oqtane.Application.Shared.csproj" />
</Solution>

View File

@@ -0,0 +1,22 @@
# Oqtane Application Template
This is a Visual Studio Project Template designed for Oqtane development projects. This template relies on the native templating capabilities of the .NET Command Line Interface (CLI):
```
dotnet new install Oqtane.Application.Template
dotnet new oqtane-app -o MyCompany.MyProject
cd MyCompany.MyProject
dotnet build
cd Server
dotnet run
browse to Url
```
When using this approach you do not need to have a local copy of the oqtane.framework source code - you simply utilize Oqtane as a standard application dependency.
The solution also contains Client, Server, and Shared folders which is where you you would implement your custom functionality. An example module and theme are included for reference, and you can add additional modules and themes within the same projects by following the standard Oqtane folder/namespace conventions.
*Known Issues*
- do not use the term "Oqtane" or "Module" in your output name or else you will experience namespace conflicts

View File

@@ -0,0 +1,3 @@
using Microsoft.Extensions.Localization;
[assembly: RootNamespace("Oqtane.Application.Server")]

View File

@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Version>1.0.0</Version>
<AssemblyName>Oqtane.Application.Server.Oqtane</AssemblyName>
<PreserveCompilationContext>true</PreserveCompilationContext>
<SatelliteResourceLanguages>none</SatelliteResourceLanguages>
<CompressionEnabled>false</CompressionEnabled>
<StaticWebAssetsFingerprintContent>false</StaticWebAssetsFingerprintContent>
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
<RequiresAspNetWebAssets>true</RequiresAspNetWebAssets>
</PropertyGroup>
<ItemGroup>
<Compile Remove="wwwroot\Modules\Templates\**" />
<Compile Remove="wwwroot\Themes\Templates\**" />
<Content Remove="wwwroot\Modules\Templates\**" />
<Content Remove="wwwroot\Themes\Templates\**" />
<EmbeddedResource Remove="wwwroot\Modules\Templates\**" />
<EmbeddedResource Remove="wwwroot\Themes\Templates\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Client\Oqtane.Application.Client.csproj" />
<ProjectReference Include="..\Shared\Oqtane.Application.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Oqtane.Server" Version="10.0.3" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,55 @@
using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Oqtane.Extensions;
using Oqtane.Infrastructure;
using Oqtane.Shared;
namespace Oqtane.Application.Server
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
AppDomain.CurrentDomain.SetData(Constants.DataDirectory, Path.Combine(builder.Environment.ContentRootPath, "Data"));
var configurationBuilder = new ConfigurationBuilder()
.SetBasePath(builder.Environment.ContentRootPath)
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", true, true)
.AddEnvironmentVariables();
var configuration = configurationBuilder.Build();
builder.Services.AddOqtane(configuration, builder.Environment);
var app = builder.Build();
var corsService = app.Services.GetRequiredService<ICorsService>();
var corsPolicyProvider = app.Services.GetRequiredService<ICorsPolicyProvider>();
var syncManager = app.Services.GetRequiredService<ISyncManager>();
app.UseOqtane(configuration, builder.Environment, corsService, corsPolicyProvider, syncManager);
var databaseManager = app.Services.GetService<IDatabaseManager>();
var install = databaseManager.Install();
if (!string.IsNullOrEmpty(install.Message))
{
var filelogger = app.Services.GetRequiredService<ILogger<Program>>();
if (filelogger != null)
{
filelogger.LogError($"[Oqtane.Server.Program.Main] {install.Message}");
}
}
else
{
app.Run();
}
}
}
}

View File

@@ -0,0 +1,25 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "http://localhost:44358",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:44359;http://localhost:44358",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,63 @@
{
"RenderMode": "Static",
"Runtime": "Server",
"Database": {
"DefaultDBType": ""
},
"ConnectionStrings": {
"DefaultConnection": ""
},
"Installation": {
"DefaultAlias": "",
"HostPassword": "",
"HostEmail": "",
"SiteTemplate": "",
"DefaultTheme": "",
"DefaultContainer": ""
},
"Localization": {
"DefaultCulture": "en"
},
"AvailableDatabases": [
{
"Name": "LocalDB",
"ControlType": "Oqtane.Installer.Controls.LocalDBConfig, Oqtane.Client",
"DBType": "Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Server"
},
{
"Name": "SQL Server",
"ControlType": "Oqtane.Installer.Controls.SqlServerConfig, Oqtane.Client",
"DBType": "Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Server"
},
{
"Name": "SQLite",
"ControlType": "Oqtane.Installer.Controls.SqliteConfig, Oqtane.Client",
"DBType": "Oqtane.Database.Sqlite.SqliteDatabase, Oqtane.Server"
},
{
"Name": "MySQL",
"ControlType": "Oqtane.Installer.Controls.MySQLConfig, Oqtane.Client",
"DBType": "Oqtane.Database.MySQL.MySQLDatabase, Oqtane.Server"
},
{
"Name": "PostgreSQL",
"ControlType": "Oqtane.Installer.Controls.PostgreSQLConfig, Oqtane.Client",
"DBType": "Oqtane.Database.PostgreSQL.PostgreSQLDatabase, Oqtane.Server"
},
{
"Name": "Azure SQL",
"ControlType": "Oqtane.Installer.Controls.AzureSqlConfig, Oqtane.Client",
"DBType": "Oqtane.Database.SqlServer.SqlServerDatabase, Oqtane.Server"
}
],
"Logging": {
"FileLogger": {
"LogLevel": {
"Default": "Error"
}
},
"LogLevel": {
"Default": "Information"
}
}
}

View File

@@ -0,0 +1,107 @@
@using Oqtane.Modules.Controls
@using [Owner].Module.[Module].Services
@using [Owner].Module.[Module].Models
@namespace [Owner].Module.[Module]
@inherits ModuleBase
@inject I[Module]Service [Module]Service
@inject NavigationManager NavigationManager
@inject IStringLocalizer<Edit> Localizer
<form @ref="form" class="@(validated ? " was-validated" : "needs-validation" )" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter a name" ResourceKey="Name">Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" required />
</div>
</div>
</div>
<button type="button" class="btn btn-success" @onclick="Save">@Localizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
<br /><br />
@if (PageState.Action == "Edit")
{
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
}
</form>
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Actions => "Add,Edit";
public override string Title => "Manage [Module]";
private ElementReference form;
private bool validated = false;
private int _id;
private string _name;
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
protected override async Task OnInitializedAsync()
{
try
{
if (PageState.Action == "Edit")
{
_id = Int32.Parse(PageState.QueryString["id"]);
[Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
if ([Module] != null)
{
_name = [Module].Name;
_createdby = [Module].CreatedBy;
_createdon = [Module].CreatedOn;
_modifiedby = [Module].ModifiedBy;
_modifiedon = [Module].ModifiedOn;
}
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading [Module] {[Module]Id} {Error}", _id, ex.Message);
AddModuleMessage(Localizer["Message.LoadError"], MessageType.Error);
}
}
private async Task Save()
{
try
{
validated = true;
var interop = new Oqtane.UI.Interop(JSRuntime);
if (await interop.FormValid(form))
{
if (PageState.Action == "Add")
{
[Module] [Module] = new [Module]();
[Module].ModuleId = ModuleState.ModuleId;
[Module].Name = _name;
[Module] = await [Module]Service.Add[Module]Async([Module]);
await logger.LogInformation("[Module] Added {[Module]}", [Module]);
}
else
{
[Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
[Module].Name = _name;
await [Module]Service.Update[Module]Async([Module]);
await logger.LogInformation("[Module] Updated {[Module]}", [Module]);
}
NavigationManager.NavigateTo(NavigateUrl());
}
else
{
AddModuleMessage(Localizer["Message.SaveValidation"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving [Module] {Error}", ex.Message);
AddModuleMessage(Localizer["Message.SaveError"], MessageType.Error);
}
}
}

View File

@@ -0,0 +1,79 @@
@using [Owner].Module.[Module].Services
@using [Owner].Module.[Module].Models
@namespace [Owner].Module.[Module]
@inherits ModuleBase
@inject I[Module]Service [Module]Service
@inject NavigationManager NavigationManager
@inject IStringLocalizer<Index> Localizer
@if (_[Module]s == null)
{
<p><em>Loading...</em></p>
}
else
{
<ActionLink Action="Add" Security="SecurityAccessLevel.Edit" Text="Add [Module]" ResourceKey="Add" />
<br />
<br />
@if (@_[Module]s.Count != 0)
{
<Pager Items="@_[Module]s">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@Localizer["Name"]</th>
</Header>
<Row>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.[Module]Id.ToString())" ResourceKey="Edit" /></td>
<td><ActionDialog Header="Delete [Module]" Message="Are You Sure You Wish To Delete This [Module]?" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" ResourceKey="Delete" Id="@context.[Module]Id.ToString()" /></td>
<td>@context.Name</td>
</Row>
</Pager>
}
else
{
<p>@Localizer["Message.DisplayNone"]</p>
}
}
@code {
public override string RenderMode => RenderModes.Static;
public override List<Resource> Resources => new List<Resource>()
{
new Stylesheet(ModulePath() + "Module.css"),
new Script(ModulePath() + "Module.js")
};
List<[Module]> _[Module]s;
protected override async Task OnInitializedAsync()
{
try
{
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading [Module] {Error}", ex.Message);
AddModuleMessage(Localizer["Message.LoadError"], MessageType.Error);
}
}
private async Task Delete([Module] [Module])
{
try
{
await [Module]Service.Delete[Module]Async([Module].[Module]Id, ModuleState.ModuleId);
await logger.LogInformation("[Module] Deleted {[Module]}", [Module]);
_[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting [Module] {[Module]} {Error}", [Module], ex.Message);
AddModuleMessage(Localizer["Message.DeleteError"], MessageType.Error);
}
}
}

View File

@@ -0,0 +1,15 @@
using Microsoft.JSInterop;
using System.Threading.Tasks;
namespace [Owner].Module.[Module]
{
public class Interop
{
private readonly IJSRuntime _jsRuntime;
public Interop(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
}
}

View File

@@ -0,0 +1,16 @@
using Oqtane.Models;
using Oqtane.Modules;
namespace [Owner].Module.[Module]
{
public class ModuleInfo : IModule
{
public ModuleDefinition ModuleDefinition => new ModuleDefinition
{
Name = "[Module]",
Description = "[Description]",
Version = "1.0.0",
ServerManagerType = "[ServerManagerType]"
};
}
}

View File

@@ -0,0 +1,47 @@
@namespace [Owner].Module.[Module]
@inherits ModuleBase
@inject ISettingService SettingService
@inject IStringLocalizer<Settings> Localizer
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="value" HelpText="Enter a value" ResourceKey="SettingName" ResourceType="@resourceType">Name: </Label>
<div class="col-sm-9">
<input id="value" type="text" class="form-control" @bind="@_value" />
</div>
</div>
</div>
@code {
private string resourceType = "[Owner].Module.[Module].Settings, [Owner].Module.[Module].Client.Oqtane"; // for localization
public override string Title => "[Module] Settings";
string _value;
protected override async Task OnInitializedAsync()
{
try
{
Dictionary<string, string> settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
_value = SettingService.GetSetting(settings, "SettingName", "");
}
catch (Exception ex)
{
AddModuleMessage(ex.Message, MessageType.Error);
}
}
public async Task UpdateSettings()
{
try
{
var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
settings = SettingService.SetSetting(settings, "SettingName", _value);
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
}
catch (Exception ex)
{
AddModuleMessage(ex.Message, MessageType.Error);
}
}
}

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Name.Text" xml:space="preserve">
<value>Name: </value>
</data>
<data name="Name.HelpText" xml:space="preserve">
<value>Enter the name</value>
</data>
<data name="Save" xml:space="preserve">
<value>Save</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="Message.LoadError" xml:space="preserve">
<value>Error Loading [Module]</value>
</data>
<data name="Message.SaveValidation" xml:space="preserve">
<value>Please Provide All Required Information</value>
</data>
<data name="Message.SaveError" xml:space="preserve">
<value>Error Saving [Module]</value>
</data>
</root>

View File

@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Name" xml:space="preserve">
<value>Name</value>
</data>
<data name="Add.Text" xml:space="preserve">
<value>Add [Module]</value>
</data>
<data name="Edit.Text" xml:space="preserve">
<value>Edit</value>
</data>
<data name="Delete.Text" xml:space="preserve">
<value>Delete</value>
</data>
<data name="Delete.Header" xml:space="preserve">
<value>Delete [Module]</value>
</data>
<data name="Delete.Message" xml:space="preserve">
<value>Are You Sure You Wish To Delete This [Module]?</value>
</data>
<data name="Message.DisplayNone" xml:space="preserve">
<value>No [Module]s To Display</value>
</data>
<data name="Message.LoadError" xml:space="preserve">
<value>Error Loading [Module]</value>
</data>
<data name="Message.DeleteError" xml:space="preserve">
<value>Error Deleting [Module]</value>
</data>
</root>

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SettingName.Text" xml:space="preserve">
<value>Name: </value>
</data>
<data name="SettingName.HelpText" xml:space="preserve">
<value>Enter a value</value>
</data>
</root>

View File

@@ -0,0 +1,55 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Oqtane.Services;
using Oqtane.Shared;
namespace [Owner].Module.[Module].Services
{
public interface I[Module]Service
{
Task<List<Models.[Module]>> Get[Module]sAsync(int ModuleId);
Task<Models.[Module]> Get[Module]Async(int [Module]Id, int ModuleId);
Task<Models.[Module]> Add[Module]Async(Models.[Module] [Module]);
Task<Models.[Module]> Update[Module]Async(Models.[Module] [Module]);
Task Delete[Module]Async(int [Module]Id, int ModuleId);
}
public class [Module]Service : ServiceBase, I[Module]Service
{
public [Module]Service(HttpClient http, SiteState siteState) : base(http, siteState) { }
private string Apiurl => CreateApiUrl("[Module]");
public async Task<List<Models.[Module]>> Get[Module]sAsync(int ModuleId)
{
List<Models.[Module]> [Module]s = await GetJsonAsync<List<Models.[Module]>>(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", EntityNames.Module, ModuleId), Enumerable.Empty<Models.[Module]>().ToList());
return [Module]s.OrderBy(item => item.Name).ToList();
}
public async Task<Models.[Module]> Get[Module]Async(int [Module]Id, int ModuleId)
{
return await GetJsonAsync<Models.[Module]>(CreateAuthorizationPolicyUrl($"{Apiurl}/{[Module]Id}/{ModuleId}", EntityNames.Module, ModuleId));
}
public async Task<Models.[Module]> Add[Module]Async(Models.[Module] [Module])
{
return await PostJsonAsync<Models.[Module]>(CreateAuthorizationPolicyUrl($"{Apiurl}", EntityNames.Module, [Module].ModuleId), [Module]);
}
public async Task<Models.[Module]> Update[Module]Async(Models.[Module] [Module])
{
return await PutJsonAsync<Models.[Module]>(CreateAuthorizationPolicyUrl($"{Apiurl}/{[Module].[Module]Id}", EntityNames.Module, [Module].ModuleId), [Module]);
}
public async Task Delete[Module]Async(int [Module]Id, int ModuleId)
{
await DeleteAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{[Module]Id}/{ModuleId}", EntityNames.Module, ModuleId));
}
}
}

View File

@@ -0,0 +1,18 @@
using Microsoft.Extensions.DependencyInjection;
using System.Linq;
using Oqtane.Services;
using [Owner].Module.[Module].Services;
namespace [Owner].Module.[Module].Startup
{
public class ClientStartup : IClientStartup
{
public void ConfigureServices(IServiceCollection services)
{
if (!services.Any(s => s.ServiceType == typeof(I[Module]Service)))
{
services.AddScoped<I[Module]Service, [Module]Service>();
}
}
}
}

View File

@@ -0,0 +1,114 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Oqtane.Shared;
using Oqtane.Enums;
using Oqtane.Infrastructure;
using [Owner].Module.[Module].Services;
using Oqtane.Controllers;
using System.Net;
using System.Threading.Tasks;
namespace [Owner].Module.[Module].Controllers
{
[Route(ControllerRoutes.ApiRoute)]
public class [Module]Controller : ModuleControllerBase
{
private readonly I[Module]Service _[Module]Service;
public [Module]Controller(I[Module]Service [Module]Service, ILogManager logger, IHttpContextAccessor accessor) : base(logger, accessor)
{
_[Module]Service = [Module]Service;
}
// GET: api/<controller>?moduleid=x
[HttpGet]
[Authorize(Policy = PolicyNames.ViewModule)]
public async Task<IEnumerable<Models.[Module]>> Get(string moduleid)
{
int ModuleId;
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
{
return await _[Module]Service.Get[Module]sAsync(ModuleId);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Get Attempt {ModuleId}", moduleid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
}
// GET api/<controller>/5
[HttpGet("{id}/{moduleid}")]
[Authorize(Policy = PolicyNames.ViewModule)]
public async Task<Models.[Module]> Get(int id, int moduleid)
{
Models.[Module] [Module] = await _[Module]Service.Get[Module]Async(id, moduleid);
if ([Module] != null && IsAuthorizedEntityId(EntityNames.Module, [Module].ModuleId))
{
return [Module];
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Get Attempt {[Module]Id} {ModuleId}", id, moduleid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
}
// POST api/<controller>
[HttpPost]
[Authorize(Policy = PolicyNames.EditModule)]
public async Task<Models.[Module]> Post([FromBody] Models.[Module] [Module])
{
if (ModelState.IsValid && IsAuthorizedEntityId(EntityNames.Module, [Module].ModuleId))
{
[Module] = await _[Module]Service.Add[Module]Async([Module]);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Post Attempt {[Module]}", [Module]);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
[Module] = null;
}
return [Module];
}
// PUT api/<controller>/5
[HttpPut("{id}")]
[Authorize(Policy = PolicyNames.EditModule)]
public async Task<Models.[Module]> Put(int id, [FromBody] Models.[Module] [Module])
{
if (ModelState.IsValid && [Module].[Module]Id == id && IsAuthorizedEntityId(EntityNames.Module, [Module].ModuleId))
{
[Module] = await _[Module]Service.Update[Module]Async([Module]);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Put Attempt {[Module]}", [Module]);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
[Module] = null;
}
return [Module];
}
// DELETE api/<controller>/5
[HttpDelete("{id}/{moduleid}")]
[Authorize(Policy = PolicyNames.EditModule)]
public async Task Delete(int id, int moduleid)
{
Models.[Module] [Module] = await _[Module]Service.Get[Module]Async(id, moduleid);
if ([Module] != null && IsAuthorizedEntityId(EntityNames.Module, [Module].ModuleId))
{
await _[Module]Service.Delete[Module]Async(id, [Module].ModuleId);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Delete Attempt {[Module]Id} {ModuleId}", id, moduleid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
}
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Oqtane.Modules;
using Oqtane.Models;
using Oqtane.Infrastructure;
using Oqtane.Interfaces;
using Oqtane.Enums;
using Oqtane.Repository;
using [Owner].Module.[Module].Repository;
using System.Threading.Tasks;
namespace [Owner].Module.[Module].Manager
{
public class [Module]Manager : MigratableModuleBase, IInstallable, IPortable, ISearchable
{
private readonly I[Module]Repository _[Module]Repository;
private readonly IDBContextDependencies _DBContextDependencies;
public [Module]Manager(I[Module]Repository [Module]Repository, IDBContextDependencies DBContextDependencies)
{
_[Module]Repository = [Module]Repository;
_DBContextDependencies = DBContextDependencies;
}
public bool Install(Tenant tenant, string version)
{
return Migrate(new [Module]Context(_DBContextDependencies), tenant, MigrationType.Up);
}
public bool Uninstall(Tenant tenant)
{
return Migrate(new [Module]Context(_DBContextDependencies), tenant, MigrationType.Down);
}
public string ExportModule(Oqtane.Models.Module module)
{
string content = "";
List<Models.[Module]> [Module]s = _[Module]Repository.Get[Module]s(module.ModuleId).ToList();
if ([Module]s != null)
{
content = JsonSerializer.Serialize([Module]s);
}
return content;
}
public void ImportModule(Oqtane.Models.Module module, string content, string version)
{
List<Models.[Module]> [Module]s = null;
if (!string.IsNullOrEmpty(content))
{
[Module]s = JsonSerializer.Deserialize<List<Models.[Module]>>(content);
}
if ([Module]s != null)
{
foreach(var [Module] in [Module]s)
{
_[Module]Repository.Add[Module](new Models.[Module] { ModuleId = module.ModuleId, Name = [Module].Name });
}
}
}
public Task<List<SearchContent>> GetSearchContentsAsync(PageModule pageModule, DateTime lastIndexedOn)
{
var searchContentList = new List<SearchContent>();
foreach (var [Module] in _[Module]Repository.Get[Module]s(pageModule.ModuleId))
{
if ([Module].ModifiedOn >= lastIndexedOn)
{
searchContentList.Add(new SearchContent
{
EntityName = "[Owner][Module]",
EntityId = [Module].[Module]Id.ToString(),
Title = [Module].Name,
Body = [Module].Name,
ContentModifiedBy = [Module].ModifiedBy,
ContentModifiedOn = [Module].ModifiedOn
});
}
}
return Task.FromResult(searchContentList);
}
}
}

View File

@@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Databases.Interfaces;
using Oqtane.Migrations;
using [Owner].Module.[Module].Migrations.EntityBuilders;
using [Owner].Module.[Module].Repository;
namespace [Owner].Module.[Module].Migrations
{
[DbContext(typeof([Module]Context))]
[Migration("[Owner].Module.[Module].01.00.00.00")]
public class [Module]Initialize : MultiDatabaseMigration
{
public [Module]Initialize(IDatabase database) : base(database)
{
}
protected override void Up(MigrationBuilder migrationBuilder)
{
var entityBuilder = new [Module]EntityBuilder(migrationBuilder, ActiveDatabase);
entityBuilder.Create();
}
protected override void Down(MigrationBuilder migrationBuilder)
{
var entityBuilder = new [Module]EntityBuilder(migrationBuilder, ActiveDatabase);
entityBuilder.Drop();
}
}
}

View File

@@ -0,0 +1,36 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders;
using Oqtane.Databases.Interfaces;
using Oqtane.Migrations;
using Oqtane.Migrations.EntityBuilders;
namespace [Owner].Module.[Module].Migrations.EntityBuilders
{
public class [Module]EntityBuilder : AuditableBaseEntityBuilder<[Module]EntityBuilder>
{
private const string _entityTableName = "[Owner][Module]";
private readonly PrimaryKey<[Module]EntityBuilder> _primaryKey = new("PK_[Owner][Module]", x => x.[Module]Id);
private readonly ForeignKey<[Module]EntityBuilder> _moduleForeignKey = new("FK_[Owner][Module]_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade);
public [Module]EntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database)
{
EntityTableName = _entityTableName;
PrimaryKey = _primaryKey;
ForeignKeys.Add(_moduleForeignKey);
}
protected override [Module]EntityBuilder BuildTable(ColumnsBuilder table)
{
[Module]Id = AddAutoIncrementColumn(table,"[Module]Id");
ModuleId = AddIntegerColumn(table,"ModuleId");
Name = AddMaxStringColumn(table,"Name");
AddAuditableColumns(table);
return this;
}
public OperationBuilder<AddColumnOperation> [Module]Id { get; set; }
public OperationBuilder<AddColumnOperation> ModuleId { get; set; }
public OperationBuilder<AddColumnOperation> Name { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http;
using Oqtane.Modules;
using Oqtane.Repository;
using Oqtane.Infrastructure;
using Oqtane.Repository.Databases.Interfaces;
namespace [Owner].Module.[Module].Repository
{
public class [Module]Context : DBContextBase, ITransientService, IMultiDatabase
{
public virtual DbSet<Models.[Module]> [Module] { get; set; }
public [Module]Context(IDBContextDependencies DBContextDependencies) : base(DBContextDependencies)
{
// ContextBase handles multi-tenant database connections
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Models.[Module]>().ToTable(ActiveDatabase.RewriteName("[Owner][Module]"));
}
}
}

View File

@@ -0,0 +1,75 @@
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Collections.Generic;
using Oqtane.Modules;
namespace [Owner].Module.[Module].Repository
{
public interface I[Module]Repository
{
IEnumerable<Models.[Module]> Get[Module]s(int ModuleId);
Models.[Module] Get[Module](int [Module]Id);
Models.[Module] Get[Module](int [Module]Id, bool tracking);
Models.[Module] Add[Module](Models.[Module] [Module]);
Models.[Module] Update[Module](Models.[Module] [Module]);
void Delete[Module](int [Module]Id);
}
public class [Module]Repository : I[Module]Repository, ITransientService
{
private readonly IDbContextFactory<[Module]Context> _factory;
public [Module]Repository(IDbContextFactory<[Module]Context> factory)
{
_factory = factory;
}
public IEnumerable<Models.[Module]> Get[Module]s(int ModuleId)
{
using var db = _factory.CreateDbContext();
return db.[Module].Where(item => item.ModuleId == ModuleId).ToList();
}
public Models.[Module] Get[Module](int [Module]Id)
{
return Get[Module]([Module]Id, true);
}
public Models.[Module] Get[Module](int [Module]Id, bool tracking)
{
using var db = _factory.CreateDbContext();
if (tracking)
{
return db.[Module].Find([Module]Id);
}
else
{
return db.[Module].AsNoTracking().FirstOrDefault(item => item.[Module]Id == [Module]Id);
}
}
public Models.[Module] Add[Module](Models.[Module] [Module])
{
using var db = _factory.CreateDbContext();
db.[Module].Add([Module]);
db.SaveChanges();
return [Module];
}
public Models.[Module] Update[Module](Models.[Module] [Module])
{
using var db = _factory.CreateDbContext();
db.Entry([Module]).State = EntityState.Modified;
db.SaveChanges();
return [Module];
}
public void Delete[Module](int [Module]Id)
{
using var db = _factory.CreateDbContext();
Models.[Module] [Module] = db.[Module].Find([Module]Id);
db.[Module].Remove([Module]);
db.SaveChanges();
}
}
}

View File

@@ -0,0 +1,101 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Oqtane.Enums;
using Oqtane.Infrastructure;
using Oqtane.Models;
using Oqtane.Security;
using Oqtane.Shared;
using [Owner].Module.[Module].Repository;
namespace [Owner].Module.[Module].Services
{
public class Server[Module]Service : I[Module]Service
{
private readonly I[Module]Repository _[Module]Repository;
private readonly IUserPermissions _userPermissions;
private readonly ILogManager _logger;
private readonly IHttpContextAccessor _accessor;
private readonly Alias _alias;
public Server[Module]Service(I[Module]Repository [Module]Repository, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor)
{
_[Module]Repository = [Module]Repository;
_userPermissions = userPermissions;
_logger = logger;
_accessor = accessor;
_alias = tenantManager.GetAlias();
}
public Task<List<Models.[Module]>> Get[Module]sAsync(int ModuleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
{
return Task.FromResult(_[Module]Repository.Get[Module]s(ModuleId).ToList());
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Get Attempt {ModuleId}", ModuleId);
return null;
}
}
public Task<Models.[Module]> Get[Module]Async(int [Module]Id, int ModuleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
{
return Task.FromResult(_[Module]Repository.Get[Module]([Module]Id));
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Get Attempt {[Module]Id} {ModuleId}", [Module]Id, ModuleId);
return null;
}
}
public Task<Models.[Module]> Add[Module]Async(Models.[Module] [Module])
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, [Module].ModuleId, PermissionNames.Edit))
{
[Module] = _[Module]Repository.Add[Module]([Module]);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "[Module] Added {[Module]}", [Module]);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Add Attempt {[Module]}", [Module]);
[Module] = null;
}
return Task.FromResult([Module]);
}
public Task<Models.[Module]> Update[Module]Async(Models.[Module] [Module])
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, [Module].ModuleId, PermissionNames.Edit))
{
[Module] = _[Module]Repository.Update[Module]([Module]);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "[Module] Updated {[Module]}", [Module]);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Update Attempt {[Module]}", [Module]);
[Module] = null;
}
return Task.FromResult([Module]);
}
public Task Delete[Module]Async(int [Module]Id, int ModuleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.Edit))
{
_[Module]Repository.Delete[Module]([Module]Id);
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", [Module]Id);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized [Module] Delete Attempt {[Module]Id} {ModuleId}", [Module]Id, ModuleId);
}
return Task.CompletedTask;
}
}
}

View File

@@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Oqtane.Infrastructure;

View File

@@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Oqtane.Models;
namespace [Owner].Module.[Module].Models
{
[Table("[Owner][Module]")]
public class [Module] : ModelBase
{
[Key]
public int [Module]Id { get; set; }
public int ModuleId { get; set; }
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
{
"Title": "Default Module Template",
"Type": "Internal",
"Version": "10.0.0",
"Namespace": "[Owner].Module.[Module]"
}

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -117,16 +117,10 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="InsertImage" xml:space="preserve">
<value>Insert Image</value>
<data name="Title.HelpText" xml:space="preserve">
<value>Specify If The Module Title Should Be Displayed</value>
</data>
<data name="Close" xml:space="preserve">
<value>Close</value>
</data>
<data name="Message.Require.Image" xml:space="preserve">
<value>You Must Select An Image To Insert</value>
</data>
<data name="Placeholder" xml:space="preserve">
<value>Enter Your Content...</value>
<data name="Title.Text" xml:space="preserve">
<value>Display Title</value>
</data>
</root>

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Login.HelpText" xml:space="preserve">
<value>Specify if a Login option should be displayed. Note that this option does not prevent the login page from being accessible via a direct url.</value>
</data>
<data name="Login.Text" xml:space="preserve">
<value>Show Login?</value>
</data>
<data name="Register.HelpText" xml:space="preserve">
<value>Specify if a Register option should be displayed. Note that this option is also dependent on the Allow Registration option in Site Settings.</value>
</data>
<data name="Register.Text" xml:space="preserve">
<value>Show Register?</value>
</data>
<data name="Scope.HelpText" xml:space="preserve">
<value>Specify if the settings are applicable to this page or the entire site.</value>
</data>
<data name="Scope.Text" xml:space="preserve">
<value>Setting Scope:</value>
</data>
</root>

View File

@@ -0,0 +1,46 @@
@namespace [Owner].Theme.[Theme]
@inherits ContainerBase
@inject ISettingService SettingService
<div class="@_classes">
@if (_title && ModuleState.Title != "-")
{
<div class="row px-4">
<div class="d-flex flex-nowrap">
<ModuleActions /><h2><ModuleTitle /></h2>
</div>
<hr class="app-rule" />
</div>
}
else
{
<ModuleActions />
}
<div class="row px-4">
<div class="container-fluid">
<ModuleInstance />
</div>
</div>
</div>
@code {
public override string Name => "[Owner] [Theme] - Container1";
private bool _title = true;
private string _classes = "container-fluid";
protected override void OnParametersSet()
{
try
{
_title = bool.Parse(SettingService.GetSetting(ModuleState.Settings, GetType().Namespace + ":Title", "true"));
}
catch
{
// error loading container settings
}
}
}

View File

@@ -0,0 +1,50 @@
@namespace [Owner].Theme.[Theme]
@inherits ModuleBase
@implements Oqtane.Interfaces.ISettingsControl
@inject ISettingService SettingService
@attribute [OqtaneIgnore]
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="title" ResourceKey="Title" ResourceType="@resourceType" HelpText="Specify If The Module Title Should Be Displayed">Display Title?</Label>
<div class="col-sm-9">
<select id="title" class="form-select" @bind="@_title">
<option value="true">Yes</option>
<option value="false">No</option>
</select>
</div>
</div>
</div>
@code {
private string resourceType = "[Owner].Theme.[Theme].ContainerSettings, [Owner].Theme.[Theme].Client.Oqtane"; // for localization
private string _title = "true";
protected override void OnInitialized()
{
try
{
_title = SettingService.GetSetting(ModuleState.Settings, GetType().Namespace + ":Title", "true");
}
catch (Exception ex)
{
AddModuleMessage(ex.Message, MessageType.Error);
}
}
public async Task UpdateSettings()
{
try
{
var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Title", _title);
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
}
catch (Exception ex)
{
AddModuleMessage(ex.Message, MessageType.Error);
}
}
}

View File

@@ -0,0 +1,118 @@
@namespace [Owner].Theme.[Theme]
@inherits ThemeBase
@inject ISettingService SettingService
<main role="main">
<nav class="navbar navbar-dark bg-primary fixed-top">
<Logo /><Menu Orientation="Horizontal" />
<div class="controls ms-auto">
<div class="controls-group"><UserProfile ShowRegister="@_register" /> <Login ShowLogin="@_login" /> <ControlPanel ButtonClass="btn-outline-light" /></div>
</div>
</nav>
<div class="content">
<div class="container">
<div class="row">
<div class="col-md-12">
<Pane Name="@PaneNames.Admin" />
</div>
</div>
</div>
<Pane Name="Top Full Width" />
<div class="container">
<div class="row">
<div class="col-md-12">
<Pane Name="Top 100%" />
</div>
</div>
<div class="row">
<div class="col-md-6">
<Pane Name="Left 50%" />
</div>
<div class="col-md-6">
<Pane Name="Right 50%" />
</div>
</div>
<div class="row">
<div class="col-md-4">
<Pane Name="Left 33%" />
</div>
<div class="col-md-4">
<Pane Name="Center 33%" />
</div>
<div class="col-md-4">
<Pane Name="Right 33%" />
</div>
</div>
<div class="row">
<div class="col-md-3">
<Pane Name="Left Outer 25%" />
</div>
<div class="col-md-3">
<Pane Name="Left Inner 25%" />
</div>
<div class="col-md-3">
<Pane Name="Right Inner 25%" />
</div>
<div class="col-md-3">
<Pane Name="Right Outer 25%" />
</div>
</div>
<div class="row">
<div class="col-md-3">
<Pane Name="Left 25%" />
</div>
<div class="col-md-6">
<Pane Name="Center 50%" />
</div>
<div class="col-md-3">
<Pane Name="Right 25%" />
</div>
</div>
<div class="row">
<div class="col-md-8">
<Pane Name="Left Sidebar 66%" />
</div>
<div class="col-md-4">
<Pane Name="Right Sidebar 33%" />
</div>
</div>
<div class="row">
<div class="col-md-4">
<Pane Name="Left Sidebar 33%" />
</div>
<div class="col-md-8">
<Pane Name="Right Sidebar 66%" />
</div>
</div>
<div class="row">
<div class="col-md-12">
<Pane Name="Bottom 100%" />
</div>
</div>
</div>
<Pane Name="Bottom Full Width" />
</div>
</main>
@code {
public override string Name => "Theme1";
public override string Panes => PaneNames.Admin + ",Top Full Width,Top 100%,Left 50%,Right 50%,Left 33%,Center 33%,Right 33%,Left Outer 25%,Left Inner 25%,Right Inner 25%,Right Outer 25%,Left 25%,Center 50%,Right 25%,Left Sidebar 66%,Right Sidebar 33%,Left Sidebar 33%,Right Sidebar 66%,Bottom 100%,Bottom Full Width";
private bool _login = true;
private bool _register = true;
protected override void OnParametersSet()
{
try
{
var settings = SettingService.MergeSettings(PageState.Site.Settings, PageState.Page.Settings);
_login = bool.Parse(SettingService.GetSetting(settings, GetType().Namespace + ":Login", "true"));
_register = bool.Parse(SettingService.GetSetting(settings, GetType().Namespace + ":Register", "true"));
}
catch
{
// error loading theme settings
}
}
}

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
using Oqtane.Models;
using Oqtane.Themes;
using Oqtane.Shared;
namespace [Owner].Theme.[Theme]
{
public class ThemeInfo : ITheme
{
public Oqtane.Models.Theme Theme => new Oqtane.Models.Theme
{
Name = "[Owner] [Theme]",
Version = "1.0.0",
PackageName = "[Owner].Theme.[Theme]",
ThemeSettingsType = "[Owner].Theme.[Theme].ThemeSettings, [Owner].Theme.[Theme].Client.Oqtane",
ContainerSettingsType = "[Owner].Theme.[Theme].ContainerSettings, [Owner].Theme.[Theme].Client.Oqtane",
Resources = new List<Resource>()
{
// obtained from https://cdnjs.com/libraries
new Stylesheet(Constants.BootstrapStylesheetUrl, Constants.BootstrapStylesheetIntegrity, "anonymous"),
new Stylesheet("~/Theme.css"),
new Script(Constants.BootstrapScriptUrl, Constants.BootstrapScriptIntegrity, "anonymous")
}
};
}
}

View File

@@ -0,0 +1,140 @@
@namespace [Owner].Theme.[Theme]
@inherits ModuleBase
@implements Oqtane.Interfaces.ISettingsControl
@inject ISettingService SettingService
@inject IStringLocalizer<ThemeSettings> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@attribute [OqtaneIgnore]
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="scope" ResourceKey="Scope" ResourceType="@resourceType" HelpText="Specify if the settings are applicable to this page or the entire site.">Setting Scope:</Label>
<div class="col-sm-9">
<select id="scope" class="form-select" value="@_scope" @onchange="(e => ScopeChanged(e))">
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
{
<option value="site">@Localizer["Site"]</option>
}
<option value="page">@Localizer["Page"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="login" ResourceKey="Login" ResourceType="@resourceType" HelpText="Specify if a Login option should be displayed. Note that this option does not prevent the login page from being accessible via a direct url.">Show Login?</Label>
<div class="col-sm-9">
<select id="login" class="form-select" @bind="@_login">
<option value="-">&lt;@SharedLocalizer["Not Specified"]&gt;</option>
<option value="true">@SharedLocalizer["Yes"]</option>
<option value="false">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="register" ResourceKey="Register" ResourceType="@resourceType" HelpText="Specify if a Register option should be displayed. Note that this option is also dependent on the Allow Registration option in Site Settings.">Show Register?</Label>
<div class="col-sm-9">
<select id="register" class="form-select" @bind="@_register">
<option value="-">&lt;@SharedLocalizer["Not Specified"]&gt;</option>
<option value="true">@SharedLocalizer["Yes"]</option>
<option value="false">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
</div>
@code {
private int pageId = -1;
private string resourceType = "[Owner].Theme.[Theme].ThemeSettings, [Owner].Theme.[Theme].Client.Oqtane"; // for localization
private string _scope = "page";
private string _login = "-";
private string _register = "-";
protected override async Task OnInitializedAsync()
{
if (PageState.QueryString.ContainsKey("id"))
{
pageId = int.Parse(PageState.QueryString["id"]);
}
try
{
await LoadSettings();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Settings {Error}", ex.Message);
AddModuleMessage("Error Loading Settings", MessageType.Error);
}
}
private async Task LoadSettings()
{
if (_scope == "site")
{
var settings = PageState.Site.Settings;
_login = SettingService.GetSetting(settings, GetType().Namespace + ":Login", "true");
_register = SettingService.GetSetting(settings, GetType().Namespace + ":Register", "true");
}
else
{
var settings = await SettingService.GetPageSettingsAsync(pageId);
settings = SettingService.MergeSettings(PageState.Site.Settings, settings);
_login = SettingService.GetSetting(settings, GetType().Namespace + ":Login", "-");
_register = SettingService.GetSetting(settings, GetType().Namespace + ":Register", "-");
}
await Task.Yield();
}
private async Task ScopeChanged(ChangeEventArgs eventArgs)
{
try
{
_scope = (string)eventArgs.Value;
await LoadSettings();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Settings {Error}", ex.Message);
AddModuleMessage("Error Loading Settings", MessageType.Error);
}
}
public async Task UpdateSettings()
{
try
{
if (_scope == "site")
{
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
if (_login != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login);
}
if (_register != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Register", _register);
}
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
}
else
{
var settings = await SettingService.GetPageSettingsAsync(pageId);
if (_login != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login);
}
if (_register != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Register", _register);
}
await SettingService.UpdatePageSettingsAsync(settings, pageId);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Settings {Error}", ex.Message);
AddModuleMessage("Error Saving Settings", MessageType.Error);
}
}
}

View File

@@ -0,0 +1,6 @@
{
"Title": "Default Theme Template",
"Type": "Internal",
"Version": "10.0.0",
"Namespace": "[Owner].Theme.[Theme]"
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Version>1.0.0</Version>
<AssemblyName>Oqtane.Application.Shared.Oqtane</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Oqtane.Shared" Version="10.0.3" />
</ItemGroup>
</Project>

BIN
Oqtane.Application/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -1,7 +1,10 @@
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.Localization;
using Oqtane.Interfaces;
using Oqtane.Providers;
using Oqtane.Services;
using Oqtane.Shared;
using Radzen;
namespace Microsoft.Extensions.DependencyInjection
{
@@ -22,7 +25,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddScoped<SiteState>();
services.AddScoped<IInstallationService, InstallationService>();
services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>();
services.AddScoped<IThemeService, ThemeService>();
services.AddScoped<IThemeService, Oqtane.Services.ThemeService>();
services.AddScoped<IAliasService, AliasService>();
services.AddScoped<ITenantService, TenantService>();
services.AddScoped<ISiteService, SiteService>();
@@ -38,7 +41,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddScoped<ILogService, LogService>();
services.AddScoped<IJobService, JobService>();
services.AddScoped<IJobLogService, JobLogService>();
services.AddScoped<INotificationService, NotificationService>();
services.AddScoped<INotificationService, Oqtane.Services.NotificationService>();
services.AddScoped<IFolderService, FolderService>();
services.AddScoped<IFileService, FileService>();
services.AddScoped<ISiteTemplateService, SiteTemplateService>();
@@ -50,6 +53,21 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddScoped<IUrlMappingService, UrlMappingService>();
services.AddScoped<IVisitorService, VisitorService>();
services.AddScoped<ISyncService, SyncService>();
services.AddScoped<ILocalizationCookieService, LocalizationCookieService>();
services.AddScoped<ICookieConsentService, CookieConsentService>();
services.AddScoped<ITimeZoneService, TimeZoneService>();
services.AddScoped<IMigrationHistoryService, MigrationHistoryService>();
services.AddScoped<IOutputCacheService, OutputCacheService>();
// providers
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.TextAreaTextEditor>();
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.RadzenTextEditor>();
services.AddRadzenComponents();
var localizer = services.BuildServiceProvider().GetService<IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor>>();
Oqtane.Modules.Controls.RadzenEditorDefinitions.Localizer = localizer;
return services;
}

View File

@@ -0,0 +1,119 @@
@namespace Oqtane.Installer.Controls
@implements Oqtane.Interfaces.IDatabaseConfigControl
@inject IStringLocalizer<SqlServerConfig> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="server" HelpText="Enter the database server name. This might include a port number as well if you are using a cloud service." ResourceKey="Server">Server:</Label>
<div class="col-sm-9">
<input id="server" type="text" class="form-control" @bind="@_server" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="database" HelpText="Enter the name of the database" ResourceKey="Database">Database:</Label>
<div class="col-sm-9">
<input id="database" type="text" class="form-control" @bind="@_database" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="security" HelpText="Select your security method" ResourceKey="Security">Security:</Label>
<div class="col-sm-9">
<select id="security" class="form-select custom-select" @bind="@_security">
<option value="integrated" selected>@Localizer["Integrated"]</option>
<option value="custom">@Localizer["Custom"]</option>
</select>
</div>
</div>
@if (_security == "custom")
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="uid" HelpText="Enter the username to use for the database" ResourceKey="Uid">User Id:</Label>
<div class="col-sm-9">
<input id="uid" type="text" class="form-control" @bind="@_uid" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
<div class="col-sm-9">
<div class="input-group">
<input id="pwd" type="@_passwordType" class="form-control" @bind="@_pwd" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglePassword</button>
</div>
</div>
</div>
}
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="encryption" HelpText="Specify if you are using an encrypted database connection. It is highly recommended to use encryption in a production environment." ResourceKey="Encryption">Encryption:</Label>
<div class="col-sm-9">
<select id="encryption" class="form-select custom-select" @bind="@_encryption">
<option value="true">@SharedLocalizer["True"]</option>
<option value="false">@SharedLocalizer["False"]</option>
</select>
</div>
</div>
@if (_encryption == "true")
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="trustservercertificate" HelpText="Specify the type of certificate you are using for encryption. Verifiable is equivalent to False. Self Signed is equivalent to True." ResourceKey="TrustServerCertificate">Certificate:</Label>
<div class="col-sm-9">
<select id="encryption" class="form-select custom-select" @bind="@_trustservercertificate">
<option value="true">@Localizer["Self Signed"]</option>
<option value="false">@Localizer["Verifiable"]</option>
</select>
</div>
</div>
}
@code {
private string _server = "tcp:{SQL Server Name}.database.windows.net,1433";
private string _database = "{SQL Database Name}";
private string _security = "custom";
private string _uid = "{SQL Administrator Login}";
private string _pwd = String.Empty;
private string _passwordType = "password";
private string _togglePassword = string.Empty;
private string _encryption = "true";
private string _trustservercertificate = "false";
protected override void OnInitialized()
{
_togglePassword = SharedLocalizer["ShowPassword"];
}
public string GetConnectionString()
{
var connectionString = String.Empty;
if (!String.IsNullOrEmpty(_server) && !String.IsNullOrEmpty(_database))
{
connectionString = $"Data Source={_server};Initial Catalog={_database};";
}
if (_security == "integrated")
{
connectionString += "Integrated Security=SSPI;";
}
else
{
connectionString += $"User ID={_uid};Password={_pwd};";
}
connectionString += $"Encrypt={_encryption};";
connectionString += $"TrustServerCertificate={_trustservercertificate};";
return connectionString;
}
private void TogglePassword()
{
if (_passwordType == "password")
{
_passwordType = "text";
_togglePassword = SharedLocalizer["HidePassword"];
}
else
{
_passwordType = "password";
_togglePassword = SharedLocalizer["ShowPassword"];
}
}
}

View File

@@ -4,7 +4,7 @@
@inject IStringLocalizer<SharedResources> SharedLocalizer
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="server" HelpText="Enter the database server name. This might include a port number as well if you are using a cloud service (ie. servername.database.windows.net,1433) " ResourceKey="Server">Server:</Label>
<Label Class="col-sm-3" For="server" HelpText="Enter the database server name. This might include a port number as well if you are using a cloud service." ResourceKey="Server">Server:</Label>
<div class="col-sm-9">
<input id="server" type="text" class="form-control" @bind="@_server" />
</div>

View File

@@ -14,8 +14,8 @@
<div class="container">
<div class="row">
<div class="mx-auto text-center">
<img src="oqtane-black.png" />
<div style="font-weight: bold">@SharedLocalizer["Version"] @Constants.Version (.NET 8)</div>
<img src="installer-logo.png" />
<div style="font-weight: bold">@SharedLocalizer["Version"] @Constants.Version (.NET @Environment.Version.Major)</div>
</div>
</div>
<hr class="app-rule" />
@@ -71,14 +71,14 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="username" HelpText="Provide a username for the primary user account" ResourceKey="Username">Username:</Label>
<div class="col-sm-9">
<input id="username" type="text" class="form-control" @bind="@_hostUsername" />
<input id="username" type="text" class="form-control" maxlength="256" @bind="@_hostUsername" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="password" HelpText="Provide a password for the primary user account" ResourceKey="Password">Password:</Label>
<div class="col-sm-9">
<div class="input-group">
<input id="password" type="@_passwordType" class="form-control" @bind="@_hostPassword" autocomplete="new-password" />
<input id="password" type="@_passwordType" class="form-control" maxlength="256" @bind="@_hostPassword" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglePassword</button>
</div>
</div>
@@ -87,7 +87,7 @@
<Label Class="col-sm-3" For="confirm" HelpText="Please confirm the password entered above by entering it again" ResourceKey="Confirm">Confirm:</Label>
<div class="col-sm-9">
<div class="input-group">
<input id="confirm" type="@_confirmPasswordType" class="form-control" @bind="@_confirmPassword" autocomplete="new-password" />
<input id="confirm" type="@_confirmPasswordType" class="form-control" maxlength="256" @bind="@_confirmPassword" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@ToggleConfirmPassword" tabindex="-1">@_toggleConfirmPassword</button>
</div>
</div>
@@ -95,7 +95,13 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="email" HelpText="Provide the email address for the host user account" ResourceKey="Email">Email:</Label>
<div class="col-sm-9">
<input type="text" class="form-control" @bind="@_hostEmail" />
<input type="text" class="form-control" maxlength="256" @bind="@_hostEmail" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Provide the full name of the host user" ResourceKey="Name">Full Name:</Label>
<div class="col-sm-9">
<input type="text" class="form-control" maxlength="50" @bind="@_hostName" />
</div>
</div>
<div class="row mb-1 align-items-center">
@@ -153,132 +159,134 @@
private string _toggleConfirmPassword = string.Empty;
private string _confirmPassword = string.Empty;
private string _hostEmail = string.Empty;
private string _hostName = string.Empty;
private List<SiteTemplate> _templates;
private string _template = Constants.DefaultSiteTemplate;
private bool _register = true;
private string _message = string.Empty;
private string _loadingDisplay = "display: none;";
private string _message = string.Empty;
private string _loadingDisplay = "display: none;";
protected override async Task OnInitializedAsync()
{
protected override async Task OnInitializedAsync()
{
// include CSS
var content = "<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css\" integrity=\"sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==\" crossorigin=\"anonymous\" type=\"text/css\"/>";
var content = $"<link rel=\"stylesheet\" href=\"{Constants.BootstrapStylesheetUrl}\" integrity=\"{Constants.BootstrapStylesheetIntegrity}\" crossorigin=\"anonymous\" type=\"text/css\"/>";
SiteState.AppendHeadContent(content);
_togglePassword = SharedLocalizer["ShowPassword"];
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
_databases = await DatabaseService.GetDatabasesAsync();
if (_databases.Exists(item => item.IsDefault))
{
_databaseName = _databases.Find(item => item.IsDefault).Name;
}
else
{
_databaseName = "LocalDB";
}
LoadDatabaseConfigComponent();
_databases = await DatabaseService.GetDatabasesAsync();
if (_databases.Exists(item => item.IsDefault))
{
_databaseName = _databases.Find(item => item.IsDefault).Name;
}
else
{
_databaseName = Constants.DefaultDBName;
}
LoadDatabaseConfigComponent();
_templates = await SiteTemplateService.GetSiteTemplatesAsync();
}
private void DatabaseChanged(ChangeEventArgs eventArgs)
{
try
{
_databaseName = (string)eventArgs.Value;
_showConnectionString = false;
LoadDatabaseConfigComponent();
}
catch
{
_message = Localizer["Error.DbConfig.Load"];
}
}
private void DatabaseChanged(ChangeEventArgs eventArgs)
{
try
{
_databaseName = (string)eventArgs.Value;
_showConnectionString = false;
LoadDatabaseConfigComponent();
}
catch
{
_message = Localizer["Error.DbConfig.Load"];
}
}
private void LoadDatabaseConfigComponent()
{
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
if (database != null)
{
_databaseConfigType = Type.GetType(database.ControlType);
DatabaseConfigComponent = builder =>
{
builder.OpenComponent(0, _databaseConfigType);
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
builder.CloseComponent();
};
}
}
private void LoadDatabaseConfigComponent()
{
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
if (database != null)
{
_databaseConfigType = Type.GetType(database.ControlType);
DatabaseConfigComponent = builder =>
{
builder.OpenComponent(0, _databaseConfigType);
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
builder.CloseComponent();
};
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// include JavaScript
var interop = new Interop(JSRuntime);
await interop.IncludeScript("", "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js", "sha512-VK2zcvntEufaimc+efOYi622VN5ZacdnufnmX7zIhCPmjhKnOi9ZDMtg1/ug5l183f19gG1/cBstPO4D8N/Img==", "anonymous", "", "head");
}
}
var interop = new Interop(JSRuntime);
await interop.IncludeScript("", Constants.BootstrapScriptUrl, Constants.BootstrapScriptIntegrity, "anonymous", "", "head");
}
}
private async Task Install()
{
var connectionString = String.Empty;
if (_showConnectionString)
{
connectionString = _connectionString;
}
else
{
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
{
connectionString = databaseConfigControl.GetConnectionString();
}
}
private async Task Install()
{
var connectionString = String.Empty;
if (_showConnectionString)
{
connectionString = _connectionString;
}
else
{
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
{
connectionString = databaseConfigControl.GetConnectionString();
}
}
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
{
if (await UserService.ValidatePasswordAsync(_hostPassword))
{
_loadingDisplay = "";
StateHasChanged();
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@") && !string.IsNullOrEmpty(_hostName))
{
var result = await UserService.ValidateUserAsync(_hostUsername, _hostEmail, _hostPassword);
if (result.Succeeded)
{
_loadingDisplay = "";
StateHasChanged();
Uri uri = new Uri(NavigationManager.Uri);
Uri uri = new Uri(NavigationManager.Uri);
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
var config = new InstallConfig
{
DatabaseType = database.DBType,
ConnectionString = connectionString,
Aliases = uri.Authority,
HostUsername = _hostUsername,
HostPassword = _hostPassword,
HostEmail = _hostEmail,
HostName = _hostUsername,
TenantName = TenantNames.Master,
IsNewTenant = true,
SiteName = Constants.DefaultSite,
Register = _register,
SiteTemplate = _template,
RenderMode = RenderModes.Static,
Runtime = Runtimes.Server
};
var config = new InstallConfig
{
DatabaseType = database.DBType,
ConnectionString = connectionString,
Aliases = uri.Authority,
HostUsername = _hostUsername,
HostPassword = _hostPassword,
HostEmail = _hostEmail,
HostName = _hostName,
TenantName = TenantNames.Master,
IsNewTenant = true,
SiteName = Constants.DefaultSite,
Register = _register,
SiteTemplate = _template,
RenderMode = "", // provided by appsettings.json
Runtime = "" // provided by appsettings.json
};
var installation = await InstallationService.Install(config);
if (installation.Success)
{
NavigationManager.NavigateTo(uri.Scheme + "://" + uri.Authority, true);
}
else
{
_message = installation.Message;
_loadingDisplay = "display: none;";
}
}
else
{
_message = Localizer["Message.Password.Invalid"];
var installation = await InstallationService.Install(config);
if (installation.Success)
{
NavigationManager.NavigateTo(uri.Scheme + "://" + uri.Authority, true);
}
else
{
_message = installation.Message;
_loadingDisplay = "display: none;";
}
}
else
{
_message = string.Join("<br />", result.Errors.Select(i => !string.IsNullOrEmpty(i.Value) ? i.Value : Localizer[i.Key]));
}
}
else

View File

@@ -13,7 +13,7 @@
{
string url = NavigateUrl(p.Path);
<div class="col-md-2 mx-auto text-center my-3">
<NavLink class="nav-link text-body" href="@url" Match="NavLinkMatch.All">
<NavLink class="nav-link text-body" href="@url" Match="NavLinkMatch.All" @attributes="_attributes">
<h2><span class="@p.Icon" aria-hidden="true"></span></h2>
<div class="lead">@((MarkupString)SharedLocalizer[p.Name].ToString().Replace(" ", "<br />"))</div>
</NavLink>
@@ -24,13 +24,19 @@
}
@code {
private List<Page> _pages;
Dictionary<string, object> _attributes { get; set; } = new();
private List<Page> _pages;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
public override string RenderMode => RenderModes.Static;
protected override void OnInitialized()
{
if (PageState.RenderMode == RenderModes.Static && !PageState.Site.EnhancedNavigation)
{
_attributes.Add("data-enhance-nav", "true"); // Admin Dashboard utilizes enhanced navigation
}
var admin = PageState.Pages.FirstOrDefault(item => item.Path == "admin");
if (admin != null)
{

View File

@@ -40,10 +40,14 @@
</div>
</div>
</div>
<br />
<button type="button" class="btn btn-success" @onclick="SaveFile">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
<br />
<br />
@if (_name.ToLower().EndsWith(".zip"))
{
<button type="button" class="btn btn-primary mx-1" @onclick="UnzipFile">Unzip</button>
}
<br /><br />
<AuditInfo CreatedBy="@_createdBy" CreatedOn="@_createdOn" ModifiedBy="@_modifiedBy" ModifiedOn="@_modifiedOn"></AuditInfo>
</form>
}
@@ -126,4 +130,18 @@
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
}
}
private async Task UnzipFile()
{
try
{
await FileService.UnzipFileAsync(_fileId);
NavigationManager.NavigateTo(NavigateUrl());
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Unzipping File {FileId} {Error}", _fileId, ex.Message);
AddModuleMessage(Localizer["Error.File.Unzip"], MessageType.Error);
}
}
}

View File

@@ -8,67 +8,95 @@
@if (_folders != null)
{
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="parent" HelpText="Select the parent folder" ResourceKey="Parent">Parent: </Label>
<div class="col-sm-9">
<select id="parent" class="form-select" @bind="@_parentId" required>
@if (PageState.QueryString.ContainsKey("id"))
{
<option value="-1">&lt;@Localizer["NoParent"]&gt;</option>
}
@foreach (Folder folder in _folders)
{
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
}
</select>
<TabStrip>
<TabPanel Name="Settings" ResourceKey="Settings" Heading="Settings">
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="parent" HelpText="Select the parent folder" ResourceKey="Parent">Parent: </Label>
<div class="col-sm-9">
@if (_parentId == -1)
{
<select id="parent" class="form-select" @bind="@_parentId" required>
<option value="-1">&lt;@Localizer["NoParent"]&gt;</option>
</select>
}
else
{
<select id="parent" class="form-select" @bind="@_parentId" required>
@foreach (Folder folder in _folders)
{
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
}
</select>
}
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter the folder name" ResourceKey="Name">Name: </Label>
<div class="col-sm-9">
@if (_isSystem)
{
<input id="name" class="form-control" @bind="@_name" readonly />
}
else
{
<input id="name" class="form-control" @bind="@_name" maxlength="256" required />
}
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="type" HelpText="Select the folder type. Private folders are only accessible by authorized users. Public folders can be accessed by all users" ResourceKey="Type">Type: </Label>
<div class="col-sm-9">
@if (PageState.QueryString.ContainsKey("id"))
{
<input id="type" class="form-control" readonly @bind="@_type" />
}
else
{
<select id="type" class="form-select" @bind="@_type" required>
<option value="@FolderTypes.Private">@Localizer[FolderTypes.Private]</option>
<option value="@FolderTypes.Public">@Localizer[FolderTypes.Public]</option>
</select>
}
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="capacity" HelpText="Enter the maximum folder capacity (in megabytes). Specify zero if the capacity is unlimited." ResourceKey="Capacity">Capacity: </Label>
<div class="col-sm-9">
<input id="capacity" class="form-control" @bind="@_capacity" required />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="cachecontrol" HelpText="Optionally provide a Cache-Control directive for this folder. For example 'public, max-age=60' indicates that files in this folder should be cached for 60 seconds. Please note that when caching is enabled, changes to files will not be immediately reflected in the UI." ResourceKey="CacheControl">Caching: </Label>
<div class="col-sm-9">
<input id="cachecontrol" class="form-control" @bind="@_cachecontrol" maxlength="50" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="imagesizes" HelpText="Optionally enter a list of image sizes which can be generated dynamically from uploaded images (ie. 200x200,400x400). Use * to indicate the folder supports all image sizes (not recommended)." ResourceKey="ImageSizes">Image Sizes: </Label>
<div class="col-sm-9">
<input id="imagesizes" class="form-control" @bind="@_imagesizes" maxlength="512" />
</div>
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter the folder name" ResourceKey="Name">Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" maxlength="256" required />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="type" HelpText="Select the folder type. Private folders are only accessible by authorized users. Public folders can be accessed by all users" ResourceKey="Type">Type: </Label>
<div class="col-sm-9">
@if (PageState.QueryString.ContainsKey("id"))
{
<input id="type" class="form-control" readonly @bind="@_type" />
}
else
{
<select id="type" class="form-select" @bind="@_type" required>
<option value="@FolderTypes.Private">@Localizer[FolderTypes.Private]</option>
<option value="@FolderTypes.Public">@Localizer[FolderTypes.Public]</option>
</select>
}
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="imagesizes" HelpText="Enter a list of image sizes which can be generated dynamically from uploaded images (ie. 200x200,400x400). Use * to indicate the folder supports all image sizes." ResourceKey="ImageSizes">Image Sizes: </Label>
<div class="col-sm-9">
<input id="imagesizes" class="form-control" @bind="@_imagesizes" maxlength="512" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="capacity" HelpText="Enter the maximum folder capacity (in megabytes). Specify zero if the capacity is unlimited." ResourceKey="Capacity">Capacity: </Label>
<div class="col-sm-9">
<input id="capacity" class="form-control" @bind="@_capacity" required />
</div>
</div>
<div class="row mb-1 align-items-center">
<div class="col-sm-12">
<Label Class="col-sm-3" For="permissions" HelpText="Select the permissions you want for the folder" ResourceKey="Permissions">Permissions: </Label>
@if (PageState.QueryString.ContainsKey("id"))
{
<br />
<AuditInfo CreatedBy="@_createdBy" CreatedOn="@_createdOn" ModifiedBy="@_modifiedBy" ModifiedOn="@_modifiedOn"></AuditInfo>
}
</form>
</TabPanel>
<TabPanel Name="Permissions" ResourceKey="Permissions" Heading="Permissions">
<div class="container">
<div class="row mb-1 align-items-center">
<PermissionGrid EntityName="@EntityNames.Folder" PermissionNames="@(PermissionNames.Browse + "," + PermissionNames.View + "," + PermissionNames.Edit)" PermissionList="@_permissions" @ref="_permissionGrid" />
</div>
</div>
</div>
</form>
<br /><br />
</TabPanel>
</TabStrip>
<br />
@if (!_isSystem)
{
<button type="button" class="btn btn-success" @onclick="SaveFolder">@SharedLocalizer["Save"]</button>
@@ -80,11 +108,6 @@
@((MarkupString)"&nbsp;")
<ActionDialog Header="Delete Folder" Message="Are You Sure You Wish To Delete This Folder?" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFolder())" ResourceKey="DeleteFolder" />
}
<br /><br />
@if (PageState.QueryString.ContainsKey("id"))
{
<AuditInfo CreatedBy="@_createdBy" CreatedOn="@_createdOn" ModifiedBy="@_modifiedBy" ModifiedOn="@_modifiedOn"></AuditInfo>
}
}
@code {
@@ -95,8 +118,9 @@
private int _parentId = -1;
private string _name;
private string _type = FolderTypes.Private;
private string _imagesizes = string.Empty;
private string _capacity = "0";
private string _cachecontrol = string.Empty;
private string _imagesizes = string.Empty;
private bool _isSystem;
private List<Permission> _permissions = null;
private string _createdBy;
@@ -127,8 +151,9 @@
_parentId = folder.ParentId ?? -1;
_name = folder.Name;
_type = folder.Type;
_imagesizes = folder.ImageSizes;
_capacity = folder.Capacity.ToString();
_cachecontrol = folder.CacheControl;
_imagesizes = folder.ImageSizes;
_isSystem = folder.IsSystem;
_permissions = folder.PermissionList;
_createdBy = folder.CreatedBy;
@@ -188,7 +213,7 @@
{
folder.ParentId = _parentId;
}
// check for duplicate folder names
if (_folders.Any(item => item.ParentId == folder.ParentId && item.Name == _name && item.FolderId != _folderId))
{
@@ -199,8 +224,9 @@
folder.SiteId = PageState.Site.SiteId;
folder.Name = _name;
folder.Type = _type;
folder.ImageSizes = _imagesizes;
folder.Capacity = int.Parse(_capacity);
folder.CacheControl = _cachecontrol;
folder.ImageSizes = _imagesizes;
folder.IsSystem = _isSystem;
folder.PermissionList = _permissionGrid.GetPermissionList();
@@ -215,7 +241,6 @@
if (folder != null)
{
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
await logger.LogInformation("Folder Saved {Folder}", folder);
NavigationManager.NavigateTo(NavigateUrl());
}
@@ -251,17 +276,9 @@
}
if (!isparent)
{
var files = await FileService.GetFilesAsync(_folderId);
if (files.Count == 0)
{
await FolderService.DeleteFolderAsync(_folderId);
await logger.LogInformation("Folder Deleted {Folder}", _folderId);
NavigationManager.NavigateTo(NavigateUrl());
}
else
{
AddModuleMessage(Localizer["Message.Folder.Files.InvalidDelete"], MessageType.Warning);
}
await FolderService.DeleteFolderAsync(_folderId);
await logger.LogInformation("Folder Deleted {Folder}", _folderId);
NavigationManager.NavigateTo(NavigateUrl());
}
else
{

View File

@@ -3,54 +3,92 @@
@inject NavigationManager NavigationManager
@inject IFolderService FolderService
@inject IFileService FileService
@inject ISettingService SettingService
@inject IStringLocalizer<Index> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@if (_files != null)
@if (_files == null)
{
<div class="row">
<div class="col-md mb-1">
<ActionLink Action="Edit" Text="Add Folder" Class="btn btn-secondary" ResourceKey="AddFolder" />
</div>
<div class="col-md-8 mb-1">
<div class="input-group">
<span class="input-group-text">@Localizer["Folder"]:</span>
<select class="form-select" @onchange="(e => FolderChanged(e))">
@foreach (Folder folder in _folders)
{
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
}
</select>
<ActionLink Action="Edit" Text="Edit Folder" Class="btn btn-secondary" Parameters="@($"id=" + _folderId.ToString())" ResourceKey="EditFolder" />&nbsp;
<p>
<em>@SharedLocalizer["Loading"]</em>
</p>
}
else
{
<TabStrip>
<TabPanel Name="Files" Heading="Files" ResourceKey="Files">
<div class="row">
<div class="col-md mb-1">
<ActionLink Action="Edit" Text="Add Folder" Class="btn btn-secondary" ResourceKey="AddFolder" />
</div>
<div class="col-md-8 mb-1">
<div class="input-group">
<span class="input-group-text">@Localizer["Folder"]:</span>
<select class="form-select" @onchange="(e => FolderChanged(e))">
@foreach (Folder folder in _folders)
{
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
}
</select>
<ActionLink Action="Edit" Text="Edit Folder" Class="btn btn-secondary" Parameters="@($"id=" + _folderId.ToString())" ResourceKey="EditFolder" />&nbsp;
</div>
</div>
<div class="col-md mb-1 text-end">
<ActionLink Action="Add" Text="Upload Files" Parameters="@($"id=" + _folderId.ToString())" ResourceKey="UploadFiles" />
</div>
</div>
</div>
<div class="col-md mb-1 text-end">
<ActionLink Action="Add" Text="Upload Files" Parameters="@($"id=" + _folderId.ToString())" ResourceKey="UploadFiles" />
</div>
</div>
<Pager Items="@_files" SearchProperties="Name">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@SharedLocalizer["Name"]</th>
<th>@Localizer["Modified"]</th>
<th>@Localizer["Type"]</th>
<th>@Localizer["Size"]</th>
</Header>
<Row>
<td><ActionLink Action="Details" Text="Edit" Parameters="@($"id=" + context.FileId.ToString())" ResourceKey="Details" /></td>
<td><ActionDialog Header="Delete File" Message="@string.Format(Localizer["Confirm.File.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" ResourceKey="DeleteFile" /></td>
<td><a href="@context.Url" target="_new">@context.Name</a></td>
<td>@context.ModifiedOn</td>
<td>@context.Extension.ToUpper() @SharedLocalizer["File"]</td>
<td>@string.Format("{0:0.00}", ((decimal)context.Size / 1000)) KB</td>
</Row>
</Pager>
@if (_files.Count == 0)
{
<div class="text-center">@Localizer["NoFiles"]</div>
}
@if (_files.Count != 0)
{
<Pager Items="@_files" SearchProperties="Name">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@SharedLocalizer["Name"]</th>
<th>@Localizer["Modified"]</th>
<th>@Localizer["Type"]</th>
<th>@Localizer["Size"]</th>
</Header>
<Row>
<td><ActionLink Action="Details" Text="Edit" Parameters="@($"id=" + context.FileId.ToString())" ResourceKey="Details" /></td>
<td><ActionDialog Header="Delete File" Message="@string.Format(Localizer["Confirm.File.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" ResourceKey="DeleteFile" /></td>
<td><a href="@context.Url" target="_new">@context.Name</a></td>
<td>@UtcToLocal(context.ModifiedOn)</td>
<td>@context.Extension.ToUpper() @SharedLocalizer["File"]</td>
<td>@string.Format("{0:0.00}", ((decimal)context.Size / 1000)) KB</td>
</Row>
</Pager>
}
else
{
<div class="text-center">@Localizer["NoFiles"]</div>
}
</TabPanel>
<TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings" Security="SecurityAccessLevel.Admin">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="imageExt" HelpText="Enter a comma separated list of image file extensions" ResourceKey="ImageExtensions">Image Extensions: </Label>
<div class="col-sm-9">
<input id="imageExt" spellcheck="false" class="form-control" @bind="@_imageFiles" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="uploadableFileExt" HelpText="Enter a comma separated list of uploadable file extensions" ResourceKey="UploadableFileExtensions">Uploadable File Extensions: </Label>
<div class="col-sm-9">
<input id="uploadableFileExt" spellcheck="false" class="form-control" @bind="@_uploadableFiles" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="maxChunkSize" HelpText="Files are split into chunks to streamline the upload process. Specify the maximum chunk size in MB (note that higher chunk sizes should only be used on faster networks)." ResourceKey="MaxChunkSize">Max Upload Chunk Size (MB): </Label>
<div class="col-sm-9">
<input id="maxChunkSize" type="number" min="1" max="10" step="1" class="form-control" @bind="@_maxChunkSize" />
</div>
</div>
</div>
<br />
<button type="button" class="btn btn-success" @onclick="SaveSiteSettings">@SharedLocalizer["Save"]</button>
</TabPanel>
</TabStrip>
}
@code {
@@ -58,6 +96,10 @@
private int _folderId = -1;
private List<File> _files;
private string _imageFiles = string.Empty;
private string _uploadableFiles = string.Empty;
private int _maxChunkSize = 1;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
protected override async Task OnParametersSetAsync()
@@ -71,6 +113,13 @@
_folderId = _folders[0].FolderId;
await GetFiles();
}
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
_imageFiles = SettingService.GetSetting(settings, "ImageFiles", Constants.ImageFiles);
_imageFiles = (string.IsNullOrEmpty(_imageFiles)) ? Constants.ImageFiles : _imageFiles;
_uploadableFiles = SettingService.GetSetting(settings, "UploadableFiles", Constants.UploadableFiles);
_uploadableFiles = (string.IsNullOrEmpty(_uploadableFiles)) ? Constants.UploadableFiles : _uploadableFiles;
_maxChunkSize = int.Parse(SettingService.GetSetting(settings, "MaxChunkSize", "1"));
}
catch (Exception ex)
{
@@ -115,4 +164,23 @@
AddModuleMessage(string.Format(Localizer["Error.File.Delete"], file.Name), MessageType.Error);
}
}
private async Task SaveSiteSettings()
{
try
{
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
settings = SettingService.SetSetting(settings, "ImageFiles", (_imageFiles != Constants.ImageFiles) ? _imageFiles.Replace(" ", "") : "", false);
settings = SettingService.SetSetting(settings, "UploadableFiles", (_uploadableFiles != Constants.UploadableFiles) ? _uploadableFiles.Replace(" ", "") : "", false);
settings = SettingService.SetSetting(settings, "MaxChunkSize", _maxChunkSize.ToString(), false);
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
AddModuleMessage(Localizer["Success.SaveSiteSettings"], MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Site Settings {Error}", ex.Message);
AddModuleMessage(Localizer["Error.SaveSiteSettings"], MessageType.Error);
}
}
}

View File

@@ -0,0 +1,19 @@
using Oqtane.Documentation;
using Oqtane.Models;
using Oqtane.Shared;
namespace Oqtane.Modules.Admin.Files
{
[PrivateApi("Mark this as private, since it's not very useful in the public docs")]
public class ModuleInfo : IModule
{
public ModuleDefinition ModuleDefinition => new ModuleDefinition
{
Name = "File Management",
Description = "File Management",
Version = Constants.Version,
Categories = "Admin",
ServerManagerType = "Oqtane.Modules.Admin.Files.Manager.FileManager, Oqtane.Server"
};
}
}

View File

@@ -45,7 +45,7 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="retention" HelpText="Number of log entries to retain for this job" ResourceKey="RetentionLog">Retention Log (Items): </Label>
<div class="col-sm-9">
<input id="retention" type="number" min="0" step ="1" class="form-control" @bind="@_retentionHistory" maxlength="4" required />
<input id="retention" type="number" min="0" step ="1" class="form-control" @bind="@_retentionHistory" maxlength="3" required />
</div>
</div>
<div class="row mb-1 align-items-center">
@@ -56,7 +56,7 @@
<input id="starting" type="date" class="form-control" @bind="@_startDate" />
</div>
<div class="col">
<input id="starting" type="time" class="form-control" placeholder="hh:mm" @bind="@_startTime" />
<input id="starting" type="time" class="form-control" @bind="@_startTime" placeholder="hh:mm" required="@(_startDate.HasValue)" />
</div>
</div>
</div>
@@ -69,7 +69,7 @@
<input id="ending" type="date" class="form-control" @bind="@_endDate" />
</div>
<div class="col">
<input id="ending" type="time" class="form-control" placeholder="hh:mm" @bind="@_endTime" />
<input id="ending" type="time" class="form-control" placeholder="hh:mm" @bind="@_endTime" required="@(_endDate.HasValue)" />
</div>
</div>
</div>
@@ -82,7 +82,7 @@
<input id="next" type="date" class="form-control" @bind="@_nextDate" />
</div>
<div class="col">
<input id="next" type="time" class="form-control" placeholder="hh:mm" @bind="@_nextTime" />
<input id="next" type="time" class="form-control" placeholder="hh:mm" @bind="@_nextTime" required="@(_nextDate.HasValue)" />
</div>
</div>
</div>
@@ -132,13 +132,13 @@
_isEnabled = job.IsEnabled.ToString();
_interval = job.Interval.ToString();
_frequency = job.Frequency;
_startDate = Utilities.UtcAsLocalDate(job.StartDate);
_startTime = Utilities.UtcAsLocalDateTime(job.StartDate);
_endDate = Utilities.UtcAsLocalDate(job.EndDate);
_endTime = Utilities.UtcAsLocalDateTime(job.EndDate);
_startDate = UtcToLocal(job.StartDate);
_startTime = UtcToLocal(job.StartDate);
_endDate = UtcToLocal(job.EndDate);
_endTime = UtcToLocal(job.EndDate);
_retentionHistory = job.RetentionHistory.ToString();
_nextDate = Utilities.UtcAsLocalDate(job.NextExecution);
_nextTime = Utilities.UtcAsLocalDateTime(job.NextExecution);
_nextDate = UtcToLocal(job.NextExecution);
_nextTime = UtcToLocal(job.NextExecution);
createdby = job.CreatedBy;
createdon = job.CreatedOn;
modifiedby = job.ModifiedBy;
@@ -176,10 +176,18 @@
{
job.Interval = int.Parse(_interval);
}
job.StartDate = Utilities.LocalDateAndTimeAsUtc(_startDate, _startTime);
job.EndDate = Utilities.LocalDateAndTimeAsUtc(_endDate, _endTime);
job.RetentionHistory = int.Parse(_retentionHistory);
job.NextExecution = Utilities.LocalDateAndTimeAsUtc(_nextDate, _nextTime);
job.StartDate = _startDate.HasValue && _startTime.HasValue
? LocalToUtc(_startDate.GetValueOrDefault().Date.Add(_startTime.GetValueOrDefault().TimeOfDay))
: null;
job.EndDate = _endDate.HasValue && _endTime.HasValue
? LocalToUtc(_endDate.GetValueOrDefault().Date.Add(_endTime.GetValueOrDefault().TimeOfDay))
: null;
job.NextExecution = _nextDate.HasValue && _nextTime.HasValue
? LocalToUtc(_nextDate.GetValueOrDefault().Date.Add(_nextTime.GetValueOrDefault().TimeOfDay))
: null;
job.RetentionHistory = int.Parse(_retentionHistory);
try
{
@@ -198,5 +206,4 @@
AddModuleMessage(Localizer["Message.Required.JobInfo"], MessageType.Warning);
}
}
}

View File

@@ -10,9 +10,7 @@
}
else
{
<ActionLink Action="Log" Class="btn btn-secondary" Text="View Logs" ResourceKey="ViewJobs" />
<button type="button" class="btn btn-secondary" @onclick="(async () => await Refresh())">@Localizer["Refresh.Text"]</button>
<br />
<button type="button" class="btn btn-secondary" @onclick="Refresh">@Localizer["Refresh.Text"]</button>
<br />
<Pager Items="@_jobs" SearchProperties="Name">
@@ -31,7 +29,7 @@ else
<td>@context.Name</td>
<td>@DisplayStatus(context.IsEnabled, context.IsExecuting)</td>
<td>@DisplayFrequency(context.Interval, context.Frequency)</td>
<td>@context.NextExecution?.ToLocalTime()</td>
<td>@UtcToLocal(context.NextExecution)</td>
<td>
@if (context.IsStarted)
{
@@ -44,21 +42,25 @@ else
</td>
</Row>
</Pager>
<br />
<ActionLink Action="Log" Class="btn btn-secondary" Text="View All Logs" ResourceKey="ViewLogs" />
}
@code {
private List<Job> _jobs;
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
protected override async Task OnInitializedAsync()
{
await GetJobs();
}
private async Task GetJobs()
{
_jobs = await JobService.GetJobsAsync();
if (_jobs.Count == 0)
{
AddModuleMessage(string.Format(Localizer["Message.NoJobs"], NavigateUrl("admin/system")), MessageType.Warning);
}
}
}
private string DisplayStatus(bool isEnabled, bool isExecuting)
{
@@ -114,11 +116,19 @@ else
{
try
{
await JobService.StartJobAsync(jobId);
await logger.LogInformation("Job Started {JobId}", jobId);
AddModuleMessage(Localizer["Message.Job.Start"], MessageType.Success);
_jobs = await JobService.GetJobsAsync();
StateHasChanged();
Job _job = await JobService.GetJobAsync(jobId);
if (!_job.IsEnabled)
{
AddModuleMessage(Localizer["Message.Job.Disabled"], MessageType.Warning);
}
else
{
await JobService.StartJobAsync(jobId);
await logger.LogInformation("Job Started {JobId}", jobId);
AddModuleMessage(Localizer["Message.Job.Start"], MessageType.Success);
_jobs = await JobService.GetJobsAsync();
StateHasChanged();
}
}
catch (Exception ex)
{
@@ -146,7 +156,8 @@ else
private async Task Refresh()
{
_jobs = await JobService.GetJobsAsync();
StateHasChanged();
ShowProgressIndicator();
await GetJobs();
HideProgressIndicator();
}
}

View File

@@ -10,6 +10,9 @@
}
else
{
<button type="button" class="btn btn-secondary" @onclick="Refresh">@Localizer["Refresh"]</button>
<br /><br />
<Pager Items="@_jobLogs">
<Header>
<th>@SharedLocalizer["Name"]</th>
@@ -20,8 +23,8 @@ else
<Row>
<td>@context.Job.Name</td>
<td>@DisplayStatus(context.Job.IsExecuting, context.Succeeded)</td>
<td>@context.StartDate</td>
<td>@context.FinishDate</td>
<td>@UtcToLocal(context.StartDate)</td>
<td>@UtcToLocal(context.FinishDate)</td>
</Row>
<Detail>
<td colspan="4">@((MarkupString)context.Notes)</td>
@@ -36,14 +39,17 @@ else
protected override async Task OnParametersSetAsync()
{
_jobLogs = await JobLogService.GetJobLogsAsync();
await GetJobLogs();
}
private async Task GetJobLogs()
{
var jobId = -1;
if (PageState.QueryString.ContainsKey("id"))
{
_jobLogs = _jobLogs.Where(item => item.JobId == Int32.Parse(PageState.QueryString["id"])).ToList();
jobId = int.Parse(PageState.QueryString["id"]);
}
_jobLogs = _jobLogs.OrderByDescending(item => item.JobLogId).ToList();
_jobLogs = await JobLogService.GetJobLogsAsync(jobId);
}
private string DisplayStatus(bool isExecuting, bool? succeeded)
@@ -67,4 +73,11 @@ else
return status;
}
private async Task Refresh()
{
ShowProgressIndicator();
await GetJobLogs();
HideProgressIndicator();
}
}

View File

@@ -1,7 +1,6 @@
@namespace Oqtane.Modules.Admin.Languages
@inherits ModuleBase
@using System.Globalization
@using Microsoft.AspNetCore.Localization
@inject NavigationManager NavigationManager
@inject ILocalizationService LocalizationService
@inject ILanguageService LanguageService
@@ -94,7 +93,6 @@ else
var language = new Language
{
SiteId = PageState.Page.SiteId,
Name = CultureInfo.GetCultureInfo(_code).DisplayName,
Code = _code,
IsDefault = (_default == null ? false : Boolean.Parse(_default))
};
@@ -130,7 +128,7 @@ else
{
var interop = new Interop(JSRuntime);
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360);
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360, true, "Lax");
}
}

View File

@@ -1,7 +1,6 @@
@namespace Oqtane.Modules.Admin.Languages
@inherits ModuleBase
@using System.Globalization
@using Microsoft.AspNetCore.Localization
@inject NavigationManager NavigationManager
@inject ILocalizationService LocalizationService
@inject ILanguageService LanguageService
@@ -103,7 +102,7 @@ else
{
var interop = new Interop(JSRuntime);
var localizationCookieValue = CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture));
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360);
await interop.SetCookie(CookieRequestCultureProvider.DefaultCookieName, localizationCookieValue, 360, true, "Lax");
}
}

View File

@@ -8,95 +8,147 @@
@inject IStringLocalizer<Index> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<AuthorizeView Roles="@RoleNames.Registered">
<Authorizing>
<text>...</text>
</Authorizing>
<Authorized>
<ModuleMessage Message="@Localizer["Info.SignedIn"]" Type="MessageType.Info" />
</Authorized>
<NotAuthorized>
@if (!twofactor)
{
<form @ref="login" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="Oqtane-Modules-Admin-Login" @onkeypress="@(e => KeyPressed(e))">
@if (_allowexternallogin)
{
<button type="button" class="btn btn-primary" @onclick="ExternalLogin">@Localizer["Use"] @PageState.Site.Settings["ExternalLogin:ProviderName"]</button>
<br /><br />
}
@if (_allowsitelogin)
{
<div class="form-group">
<Label Class="control-label" For="username" HelpText="Please enter your Username" ResourceKey="Username">Username:</Label>
<input id="username" type="text" @ref="username" class="form-control" placeholder="@Localizer["Username.Placeholder"]" @bind="@_username" required />
</div>
<div class="form-group mt-2">
<Label Class="control-label" For="password" HelpText="Please enter your Password" ResourceKey="Password">Password:</Label>
<div class="input-group">
<input id="password" type="@_passwordtype" name="Password" class="form-control" placeholder="@Localizer["Password.Placeholder"]" @bind="@_password" required />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
<div class="form-group mt-2">
@if (!_alwaysremember)
{
<div class="form-check">
<input id="remember" type="checkbox" class="form-check-input" @bind="@_remember" />
<Label Class="control-label" For="remember" HelpText="Specify if you would like to be signed back in automatically the next time you visit this site" ResourceKey="Remember">Remember Me?</Label>
</div>
}
</div>
<button type="button" class="btn btn-primary" @onclick="Login">@SharedLocalizer["Login"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
<br /><br />
<button type="button" class="btn btn-secondary" @onclick="Forgot">@Localizer["ForgotPassword"]</button>
@if (PageState.Site.AllowRegistration)
{
<br /><br />
<NavLink href="@NavigateUrl("register")">@Localizer["Register"]</NavLink>
}
@if (PageState.User != null)
{
<ModuleMessage Message="@Localizer["Info.SignedIn"]" Type="MessageType.Info" />
}
else
{
<form @ref="login" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="Oqtane-Modules-Admin-Login" @onkeypress="@(e => KeyPressed(e))">
@switch (_action)
{
case "Login":
@if (_allowexternallogin)
{
<button type="button" class="btn btn-primary col-12" @onclick="ExternalLogin">@Localizer["Use"] @PageState.Site.Settings["ExternalLogin:ProviderName"]</button>
<hr class="app-rule mt-3 mb-2" />
}
</div>
</form>
}
else
{
<form @ref="login" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container Oqtane-Modules-Admin-Login">
<div class="form-group">
<Label Class="control-label" For="code" HelpText="Please enter the secure verification code which was sent to you by email" ResourceKey="Code">Verification Code:</Label>
<input id="code" class="form-control" @bind="@_code" placeholder="@Localizer["Code.Placeholder"]" maxlength="6" required />
</div>
<br />
<button type="button" class="btn btn-primary" @onclick="Login">@SharedLocalizer["Login"]</button>
<button type="button" class="btn btn-secondary" @onclick="Reset">@SharedLocalizer["Cancel"]</button>
</div>
</form>
}
</NotAuthorized>
</AuthorizeView>
@if (_allowsitelogin)
{
<div class="form-group text-center">
<Label Class="control-label" For="username" HelpText="Please enter your Username" ResourceKey="Username">Username:</Label>
<input id="username" type="text" @ref="username" class="form-control" placeholder="@Localizer["Username.Placeholder"]" @bind="@_username" @bind:event="oninput" required />
</div>
<div class="form-group text-center mt-2">
<Label Class="control-label" For="password" HelpText="Please enter your Password" ResourceKey="Password">Password:</Label>
<div class="input-group">
<input id="password" type="@_passwordtype" @ref="password" name="Password" class="form-control" placeholder="@Localizer["Password.Placeholder"]" @bind="@_password" @bind:event="oninput" required />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
</div>
</div>
@if (!_alwaysremember)
{
<div class="form-group text-center mt-2">
<div>
<input id="remember" type="checkbox" class="form-check-input" @bind="@_remember" />
<Label Class="control-label" For="remember" HelpText="Specify if you would like to be signed back in automatically the next time you visit this site" ResourceKey="Remember">Stay Signed In?</Label>
</div>
</div>
}
<div class="btn-group mt-2 col-12" role="group">
<button type="button" class="btn btn-primary col-6" @onclick="Login">@SharedLocalizer["Login"]</button>
<button type="button" class="btn btn-secondary col-6" @onclick="CancelLogin">@SharedLocalizer["Cancel"]</button>
</div>
<button type="button" class="btn btn-secondary col-12 mt-4" @onclick="@(() => SetAction("ForgotPassword"))">@Localizer["ForgotPassword"]</button>
}
@if (_allowloginlink)
{
<hr class="app-rule mt-3" />
<button type="button" class="btn btn-primary col-12 mt-2" @onclick="@(() => SetAction("LoginLink"))">@Localizer["UseLoginLink"]</button>
}
@if (_allowpasskeys)
{
<hr class="app-rule mt-3" />
<button type="button" class="btn btn-primary col-12 mt-2" @onclick="PasskeyLogin">@Localizer["Passkey"]</button>
}
@if (PageState.Site.AllowRegistration)
{
<hr class="app-rule mt-3" />
<div class="text-center mt-2">
<NavLink href="@_registerurl">@Localizer["Register"]</NavLink>
</div>
}
break;
case "ForgotPassword":
<div class="form-group text-center">
<Label Class="control-label" For="username" HelpText="Please enter your Username" ResourceKey="Username">Username:</Label>
<input id="username" type="text" class="form-control" placeholder="@Localizer["Username.Placeholder"]" @bind="@_username" @bind:event="oninput" required />
</div>
<div class="btn-group mt-4 col-12" role="group">
<button type="button" class="btn btn-primary col-6" @onclick="ForgotPassword">@SharedLocalizer["Send"]</button>
<button type="button" class="btn btn-secondary col-6" @onclick="@(() => SetAction("Login"))">@SharedLocalizer["Cancel"]</button>
</div>
<button type="button" class="btn btn-secondary col-12 mt-4" @onclick="@(() => SetAction("ForgotUsername"))">@Localizer["ForgotUsername"]</button>
break;
case "ForgotUsername":
<div class="form-group text-center">
<Label Class="control-label" For="email" HelpText="Please enter your Email" ResourceKey="Email">Email:</Label>
<input id="email" type="text" class="form-control" placeholder="@Localizer["Email.Placeholder"]" @bind="@_email" required />
</div>
<div class="btn-group mt-4 col-12" role="group">
<button type="button" class="btn btn-primary col-6" @onclick="ForgotUsername">@SharedLocalizer["Send"]</button>
<button type="button" class="btn btn-secondary col-6" @onclick="@(() => SetAction("Login"))">@SharedLocalizer["Cancel"]</button>
</div>
break;
case "LoginLink":
<div class="form-group text-center">
<Label Class="control-label" For="email" HelpText="Please enter your Email" ResourceKey="Email">Email:</Label>
<input id="email" type="text" class="form-control" placeholder="@Localizer["Email.Placeholder"]" @bind="@_email" required />
</div>
<div class="btn-group mt-4 col-12" role="group">
<button type="button" class="btn btn-primary col-6" @onclick="LoginLink">@SharedLocalizer["Send"]</button>
<button type="button" class="btn btn-secondary col-6" @onclick="@(() => SetAction("Login"))">@SharedLocalizer["Cancel"]</button>
</div>
break;
case "TwoFactor":
<div class="form-group">
<Label Class="control-label" For="code" HelpText="Please enter the secure verification code which was sent to you by email" ResourceKey="Code">Verification Code:</Label>
<input id="code" class="form-control" @bind="@_code" placeholder="@Localizer["Code.Placeholder"]" maxlength="6" required />
</div>
<div class="btn-group mt-4 col-12" role="group">
<button type="button" class="btn btn-primary" @onclick="Login">@SharedLocalizer["Login"]</button>
<button type="button" class="btn btn-secondary" @onclick="@(() => SetAction("Login"))">@SharedLocalizer["Cancel"]</button>
</div>
break;
}
</div>
</form>
}
@code {
private bool _allowsitelogin = true;
private string _action = "Login";
private bool _allowexternallogin = false;
private bool _allowsitelogin = true;
private bool _allowloginlink = false;
private bool _allowpasskeys = false;
private string _returnurl = string.Empty;
private ElementReference login;
private bool validated = false;
private bool twofactor = false;
private string _username = string.Empty;
private ElementReference username;
private string _password = string.Empty;
private string _passwordtype = "password";
private string _togglepassword = string.Empty;
private ElementReference password;
private bool _remember = false;
private bool _alwaysremember = false;
private string _registerurl = string.Empty;
private string _email = string.Empty;
private string _code = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
public override bool? Prerender => true;
public override List<Resource> Resources => new List<Resource>()
{
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
new Stylesheet(ModulePath() + "Module.css")
};
protected override async Task OnInitializedAsync()
@@ -105,8 +157,22 @@
{
_allowexternallogin = (SettingService.GetSetting(PageState.Site.Settings, "ExternalLogin:ProviderType", "") != "") ? true : false;
_allowsitelogin = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:AllowSiteLogin", "true"));
_allowloginlink = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:LoginLink", "false"));
_allowpasskeys = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:Passkeys", "false"));
_alwaysremember = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:AlwaysRemember", "false"));
if (!string.IsNullOrEmpty(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:RegisterUrl", "")))
{
_registerurl = SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:RegisterUrl", "");
}
else
{
_registerurl = NavigateUrl("register");
}
// PageState.ReturnUrl is not specified if user navigated directly to login page
_returnurl = (!string.IsNullOrEmpty(PageState.ReturnUrl)) ? PageState.ReturnUrl : PageState.Alias.Path;
_togglepassword = SharedLocalizer["ShowPassword"];
if (PageState.QueryString.ContainsKey("name"))
@@ -122,7 +188,7 @@
if (PageState.QueryString.ContainsKey("key"))
{
user = await UserService.LinkUserAsync(user, PageState.QueryString["token"], PageState.Site.Settings["ExternalLogin:ProviderType"], PageState.QueryString["key"], PageState.Site.Settings["ExternalLogin:ProviderName"]);
user = await UserService.AddLoginAsync(user, PageState.QueryString["token"], PageState.Site.Settings["ExternalLogin:ProviderType"], PageState.QueryString["key"], PageState.Site.Settings["ExternalLogin:ProviderName"]);
if (user != null)
{
await logger.LogInformation(LogFunction.Security, "External Login Linkage Successful For Username {Username}", _username);
@@ -140,7 +206,7 @@
user = await UserService.VerifyEmailAsync(user, PageState.QueryString["token"]);
if (user != null)
{
await logger.LogInformation(LogFunction.Security, "Email Verified For For Username {Username}", _username);
await logger.LogInformation(LogFunction.Security, "Email Verified For Username {Username}", _username);
AddModuleMessage(Localizer["Success.Account.Verified"], MessageType.Info);
}
else
@@ -154,7 +220,7 @@
{
if (PageState.QueryString.ContainsKey("status"))
{
AddModuleMessage(Localizer["ExternalLoginStatus." + PageState.QueryString["status"]], MessageType.Info);
AddModuleMessage(Localizer["ExternalLoginStatus." + PageState.QueryString["status"]], MessageType.Warning);
}
}
}
@@ -165,152 +231,34 @@
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && PageState.User == null && _allowsitelogin)
{
if (!string.IsNullOrEmpty(username.Id)) // ensure username is visible in UI
{
await username.FocusAsync();
}
}
// redirect logged in user to specified page
if (PageState.User != null && !UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
{
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
}
private async Task Login()
{
try
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(login))
{
var hybrid = (PageState.Runtime == Shared.Runtime.Hybrid);
var user = new User { SiteId = PageState.Site.SiteId, Username = _username, Password = _password, LastIPAddress = SiteState.RemoteIPAddress};
if (!twofactor)
{
_remember = _alwaysremember || _remember;
user = await UserService.LoginUserAsync(user, hybrid, _remember);
}
else
{
user = await UserService.VerifyTwoFactorAsync(user, _code);
}
if (user.IsAuthenticated)
{
await logger.LogInformation(LogFunction.Security, "Login Successful For Username {Username}", _username);
if (hybrid)
{
// hybrid apps utilize an interactive login
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
authstateprovider.NotifyAuthenticationChanged();
NavigationManager.NavigateTo(NavigateUrl(PageState.ReturnUrl, true));
}
else
{
// post back to the Login page so that the cookies are set correctly
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = WebUtility.UrlEncode(PageState.ReturnUrl) };
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
await interop.SubmitForm(url, fields);
}
}
else
{
if (SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:TwoFactor", "false") == "required" || user.TwoFactorRequired)
{
twofactor = true;
validated = false;
AddModuleMessage(Localizer["Message.TwoFactor"], MessageType.Info);
}
else
{
if (!twofactor)
{
await logger.LogInformation(LogFunction.Security, "Login Failed For Username {Username}", _username);
AddModuleMessage(Localizer["Error.Login.Fail"], MessageType.Error);
}
else
{
await logger.LogInformation(LogFunction.Security, "Two Factor Verification Failed For Username {Username}", _username);
AddModuleMessage(Localizer["Error.TwoFactor.Fail"], MessageType.Error);
}
}
}
}
else
{
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Performing Login {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Login"], MessageType.Error);
}
}
private void Cancel()
{
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
private async Task Forgot()
{
try
{
if (_username != string.Empty)
{
var user = await UserService.GetUserAsync(_username, PageState.Site.SiteId);
if (user != null)
{
await UserService.ForgotPasswordAsync(user);
await logger.LogInformation(LogFunction.Security, "Password Reset Notification Sent For Username {Username}", _username);
AddModuleMessage(Localizer["Message.ForgotUser"], MessageType.Info);
}
else
{
AddModuleMessage(Localizer["Message.UserDoesNotExist"], MessageType.Warning);
}
}
else
{
AddModuleMessage(Localizer["Message.ForgotPassword"], MessageType.Info);
}
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Resetting Password {Error}", ex.Message);
AddModuleMessage(Localizer["Error.ResetPassword"], MessageType.Error);
}
}
private void Reset()
{
twofactor = false;
_username = "";
_password = "";
ClearModuleMessage();
StateHasChanged();
}
private async Task KeyPressed(KeyboardEventArgs e)
{
if (e.Code == "Enter" || e.Code == "NumpadEnter")
{
await Login();
switch (_action)
{
case "Login":
await Login();
break;
}
}
}
private void SetAction(string action)
{
_action = action;
_username = "";
_password = "";
_email = "";
ClearModuleMessage();
StateHasChanged();
}
private void ExternalLogin()
{
NavigationManager.NavigateTo(Utilities.TenantUrl(PageState.Alias, "/pages/external?returnurl=" + WebUtility.UrlEncode(_returnurl)), true);
}
private void TogglePassword()
{
if (_passwordtype == "password")
@@ -325,9 +273,231 @@
}
}
private void ExternalLogin()
private async Task Login()
{
NavigationManager.NavigateTo(Utilities.TenantUrl(PageState.Alias, "/pages/external?returnurl=" + WebUtility.UrlEncode(PageState.ReturnUrl)), true);
try
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(login))
{
var hybrid = (PageState.Runtime == Shared.Runtime.Hybrid);
var user = new User { SiteId = PageState.Site.SiteId, Username = _username, Password = _password, LastIPAddress = SiteState.RemoteIPAddress};
if (_action == "Login")
{
_remember = _alwaysremember || _remember;
user = await UserService.LoginUserAsync(user, hybrid, _remember);
}
else
{
user = await UserService.VerifyTwoFactorAsync(user, _code);
}
if (user != null && user.IsAuthenticated)
{
await logger.LogInformation(LogFunction.Security, "Login Successful For {Username} From IP Address {IPAddress}", _username, SiteState.RemoteIPAddress);
if (hybrid)
{
// hybrid apps utilize an interactive login
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
authstateprovider.NotifyAuthenticationChanged();
NavigationManager.NavigateTo(NavigateUrl(_returnurl, true));
}
else
{
// post back to the Login page so that the cookies are set correctly
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = WebUtility.UrlEncode(_returnurl) };
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
await interop.SubmitForm(url, fields);
}
}
else
{
if (SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:TwoFactor", "false") == "required" || (user != null && user.TwoFactorRequired))
{
_action = "TwoFactor";
validated = false;
AddModuleMessage(Localizer["Message.TwoFactor"], MessageType.Info);
}
else
{
if (_action != "TwoFactor")
{
await logger.LogInformation(LogFunction.Security, "Login Failed For Username {Username}", _username);
AddModuleMessage(Localizer["Error.Login.Fail"], MessageType.Error);
}
else
{
await logger.LogInformation(LogFunction.Security, "Two Factor Verification Failed For Username {Username}", _username);
AddModuleMessage(Localizer["Error.TwoFactor.Fail"], MessageType.Error);
}
}
}
}
else
{
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Performing Login {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Login"], MessageType.Error);
}
}
private void CancelLogin()
{
NavigationManager.NavigateTo(_returnurl);
}
private async Task PasskeyLogin()
{
// post back to the Passkey page so that the cookies are set correctly
var interop = new Interop(JSRuntime);
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, operation = "request", returnurl = _returnurl };
string url = Utilities.TenantUrl(PageState.Alias, "/pages/passkey/");
await interop.SubmitForm(url, fields);
}
private async Task ForgotPassword()
{
try
{
if (!string.IsNullOrEmpty(_username))
{
if (await UserService.ForgotPasswordAsync(_username))
{
await logger.LogInformation(LogFunction.Security, "Password Reset Notification Sent For Username {Username}", _username);
AddModuleMessage(Localizer["Message.ForgotPassword"], MessageType.Info);
}
else
{
AddModuleMessage(Localizer["Message.UserDoesNotExist"], MessageType.Warning);
}
}
else
{
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Resetting Password {Error}", ex.Message);
AddModuleMessage(Localizer["Error.ResetPassword"], MessageType.Error);
}
}
private async Task ForgotUsername()
{
try
{
if (!string.IsNullOrEmpty(_email))
{
if (await UserService.ForgotUsernameAsync(_email))
{
AddModuleMessage(Localizer["Message.ForgotUsername"], MessageType.Info);
await logger.LogInformation(LogFunction.Security, "Username Reminder Notification Sent For Email {Email}", _email);
}
else
{
AddModuleMessage(Localizer["Message.UserDoesNotExist"], MessageType.Warning);
}
}
else
{
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Sending Username Reminder {Error}", ex.Message);
AddModuleMessage(Localizer["Error.ForgotUsername"], MessageType.Error);
}
}
private async Task LoginLink()
{
try
{
if (!string.IsNullOrEmpty(_email))
{
if (await UserService.SendLoginLinkAsync(_email, _returnurl))
{
AddModuleMessage(Localizer["Message.SendLoginLink"], MessageType.Info);
await logger.LogInformation(LogFunction.Security, "Login Link Sent To Email {Email}", _email);
}
else
{
AddModuleMessage(Localizer["Message.UserDoesNotExist"], MessageType.Warning);
}
}
else
{
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Sending Login Link {Error}", ex.Message);
AddModuleMessage(Localizer["Error.SendLoginLink"], MessageType.Error);
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && PageState.QueryString.ContainsKey("options"))
{
// user has initiated a passkey login
try
{
var interop = new Interop(JSRuntime);
var credential = await interop.RequestCredential(WebUtility.UrlDecode(PageState.QueryString["options"]));
if (!string.IsNullOrEmpty(credential))
{
// post back to the Passkey page so that the cookies are set correctly
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, operation = "login", credential = credential, returnurl = _returnurl };
string url = Utilities.TenantUrl(PageState.Alias, "/pages/passkey/");
await interop.SubmitForm(url, fields);
}
else
{
await logger.LogError("Passkey Login Was Not Successful");
AddModuleMessage(Localizer["Error.Passkey.Fail"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Passkey Login Was Not Successful");
AddModuleMessage(Localizer["Error.Passkey.Fail"], MessageType.Warning);
}
return;
}
if (firstRender && PageState.User == null && _allowsitelogin && _action == "Login")
{
if (string.IsNullOrEmpty(_username))
{
if (!string.IsNullOrEmpty(username.Id)) // ensure username is visible in UI
{
await username.FocusAsync();
}
}
else
{
if (!string.IsNullOrEmpty(password.Id)) // ensure password is visible in UI
{
await password.FocusAsync();
}
}
}
// redirect logged in user to specified page
if (PageState.User != null && !UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
{
NavigationManager.NavigateTo(_returnurl);
}
}
}

View File

@@ -141,7 +141,7 @@
var log = await LogService.GetLogAsync(_logId);
if (log != null)
{
_logDate = log.LogDate.ToString(CultureInfo.CurrentCulture);
_logDate = UtcToLocal(log.LogDate).Value.ToString(CultureInfo.CurrentCulture);
_level = log.Level;
_feature = log.Feature;
_function = log.Function;

View File

@@ -64,7 +64,7 @@ else
</Header>
<Row>
<td class="@GetClass(context.Function)"><ActionLink Action="Detail" Text="Details" Parameters="@($"/{context.LogId}")" ReturnUrl="@(NavigateUrl(PageState.Page.Path, AddUrlParameters(_level, _function, _rows, _page)))" ResourceKey="LogDetails" /></td>
<td class="@GetClass(context.Function)">@context.LogDate</td>
<td class="@GetClass(context.Function)">@UtcToLocal(context.LogDate)</td>
<td class="@GetClass(context.Function)">@context.Level</td>
<td class="@GetClass(context.Function)">@context.Feature</td>
<td class="@GetClass(context.Function)">@context.Function</td>

View File

@@ -101,13 +101,20 @@
<small>@SharedLocalizer["Search.By"]:</small> <strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
<br />
@if (!string.IsNullOrEmpty(context.PackageUrl))
@if (_moduledefinitions.Exists(item => item.PackageName == context.PackageId))
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
<button type="button" class="btn btn-info">@SharedLocalizer["Installed"]</button>
}
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
else
{
<a class="btn btn-success ms-2" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@SharedLocalizer["Buy"]</a>
@if (!string.IsNullOrEmpty(context.PackageUrl))
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
}
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
{
<a class="btn btn-success ms-2" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@SharedLocalizer["Buy"]</a>
}
}
<br />
</div>
@@ -125,7 +132,7 @@
<TabPanel Name="Upload" ResourceKey="Upload" Heading="Upload">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Module: </Label>
<Label Class="col-sm-3" HelpText="Upload one or more module packages." ResourceKey="Module">Module: </Label>
<div class="col-sm-9">
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" OnUpload="OnUpload" />
</div>
@@ -171,6 +178,7 @@
@code {
private bool _initialized = false;
private List<ModuleDefinition> _moduledefinitions;
private int _page = 1;
private List<Package> _packages;
private string _price = "free";
@@ -187,7 +195,8 @@
{
try
{
await LoadModuleDefinitions();
_moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
await LoadPackages();
_initialized = true;
}
catch (Exception ex)
@@ -197,24 +206,10 @@
}
}
private async Task LoadModuleDefinitions()
private async Task LoadPackages()
{
ShowProgressIndicator();
var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
_packages = await PackageService.GetPackagesAsync("module", _search, _price, "", _sort);
if (_packages != null)
{
foreach (Package package in _packages.ToArray())
{
if (moduledefinitions.Exists(item => item.PackageName == package.PackageId))
{
_packages.Remove(package);
}
}
}
HideProgressIndicator();
}
@@ -222,25 +217,25 @@
{
_price = price;
_sort = "popularity";
await LoadModuleDefinitions();
await LoadPackages();
StateHasChanged();
}
private async Task Search()
{
await LoadModuleDefinitions();
await LoadPackages();
}
private async Task Reset()
{
_page = 1;
_search = "";
await LoadModuleDefinitions();
await LoadPackages();
}
private async Task Refresh()
{
await LoadModuleDefinitions();
await LoadPackages();
}
private void OnPageChange(int page)
@@ -251,7 +246,7 @@
private async void SortChanged(ChangeEventArgs e)
{
_sort = (string)e.Value;
await LoadModuleDefinitions();
await LoadPackages();
}
private void HideModal()
@@ -310,6 +305,6 @@
private void OnUpload()
{
AddModuleMessage(string.Format(Localizer["Success.Module.Download"], NavigateUrl("admin/system")), MessageType.Success);
AddModuleMessage(string.Format(Localizer["Success.Module.Upload"], NavigateUrl("admin/system")), MessageType.Success);
}
}

View File

@@ -1,6 +1,7 @@
@namespace Oqtane.Modules.Admin.ModuleDefinitions
@inherits ModuleBase
@using System.Text.RegularExpressions
@using System.Reflection
@inject NavigationManager NavigationManager
@inject IModuleDefinitionService ModuleDefinitionService
@inject IModuleService ModuleService
@@ -27,7 +28,7 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="description" HelpText="Enter a short description for the module" ResourceKey="Description">Description: </Label>
<div class="col-sm-9">
<textarea id="description" class="form-control" @bind="@_description" rows="3" maxlength="2000" required></textarea>
<textarea id="description" class="form-control" @bind="@_description" rows="3" maxlength="2000"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
@@ -42,29 +43,32 @@
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
<div class="col-sm-9">
<select id="reference" class="form-select" @bind="@_reference" required>
@foreach (string version in _versions)
{
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
{
<option value="@(version)">@(version)</option>
}
}
<option value="local">@SharedLocalizer["LocalVersion"]</option>
</select>
</div>
</div>
@if (!string.IsNullOrEmpty(_location))
@if (_type == "External")
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="location" HelpText="Location where the module will be created" ResourceKey="Location">Location: </Label>
<Label Class="col-sm-3" For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
<div class="col-sm-9">
<input id="module" class="form-control" @bind="@_location" readonly />
<select id="reference" class="form-select" @bind="@_reference" required>
@foreach (string version in _versions)
{
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
{
<option value="@(version)">@(version)</option>
}
}
<option value="local">@SharedLocalizer["LocalVersion"]</option>
</select>
</div>
</div>
@if (!string.IsNullOrEmpty(_location))
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="location" HelpText="Location where the module will be created" ResourceKey="Location">Location: </Label>
<div class="col-sm-9">
<input id="module" class="form-control" @bind="@_location" readonly />
</div>
</div>
}
}
</div>
<button type="button" class="btn btn-success" @onclick="CreateModule">@Localizer["CreateModule"]</button>
@@ -80,9 +84,10 @@
private string _description = string.Empty;
private List<Template> _templates;
private string _template = "-";
private string _minversion = "2.0.0";
private string _type = "";
private string[] _versions;
private string _reference = "local";
private string _minversion = "2.0.0";
private string _location = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
@@ -93,6 +98,16 @@
{
AddModuleMessage(Localizer["Info.Module.Development"], MessageType.Info);
}
else
{
var entryAssemblyName = Assembly.GetEntryAssembly().GetName().Name;
if (entryAssemblyName.EndsWith(".Oqtane"))
{
// Oqtane Application assemblies end with .Server.Oqtane or .Client.Oqtane
string[] segments = entryAssemblyName.Split('.');
_owner = string.Join(".", segments, 0, segments.Length - 2);
}
}
}
protected override async Task OnParametersSetAsync()
@@ -111,6 +126,8 @@
private async Task CreateModule()
{
validated = true;
_owner = _owner.Trim();
_module = _module.Trim();
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{
@@ -118,13 +135,21 @@
{
if (IsValid(_owner) && IsValid(_module) && _owner != _module && _template != "-")
{
if (string.IsNullOrEmpty(_description)) _description = _module;
if (IsValidXML(_description))
{
if (_type == "Internal")
{
AddModuleMessage(Localizer["Success.Module.Create.Internal"], MessageType.Success);
}
var template = _templates.FirstOrDefault(item => item.Name == _template);
var moduleDefinition = new ModuleDefinition { Owner = _owner, Name = _module, Description = _description, Template = _template, Version = _reference, ModuleDefinitionName = template.Namespace };
moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition);
GetLocation();
AddModuleMessage(string.Format(Localizer["Success.Module.Create"], NavigateUrl("admin/system")), MessageType.Success);
if (_type == "External")
{
GetLocation();
AddModuleMessage(string.Format(Localizer["Success.Module.Create.External"], NavigateUrl("admin/system")), MessageType.Success);
}
}
else
{
@@ -150,7 +175,7 @@
private bool IsValid(string name)
{
// must contain letters, underscores and digits and first character must be letter or underscore
return !string.IsNullOrEmpty(name) && name.ToLower() != "module" && !name.ToLower().Contains("oqtane") && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
return !string.IsNullOrEmpty(name) && name.ToLower() != "module" && !name.ToLower().Contains("oqtane") && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_.]*$");
}
private bool IsValidXML(string description)
@@ -162,11 +187,16 @@
private void TemplateChanged(ChangeEventArgs e)
{
_template = (string)e.Value;
_minversion = "2.0.0";
if (_template != "-")
{
var template = _templates.FirstOrDefault(item => item.Name == _template);
_minversion = template.Version;
_type = template.Type;
}
else
{
_minversion = "2.0.0";
_type = "";
}
GetLocation();
}

View File

@@ -1,7 +1,6 @@
@namespace Oqtane.Modules.Admin.ModuleDefinitions
@inherits ModuleBase
@using System.Globalization
@using Microsoft.AspNetCore.Localization
@inject IModuleDefinitionService ModuleDefinitionService
@inject IPackageService PackageService
@inject ILanguageService LanguageService
@@ -10,11 +9,12 @@
@inject IStringLocalizer<SharedResources> SharedLocalizer
@inject IPageModuleService PageModuleService
@inject IModuleService ModuleService
@inject IPageService PageService
@if (_initialized)
{
<TabStrip>
<TabPanel Name="Definition" ResourceKey="Definition" Heading="Definition">
<TabPanel Name="Module" ResourceKey="Module" Heading="Module">
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
@@ -63,24 +63,7 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="packagename" HelpText="The unique name of the package from which this module was installed. This value must be specified within the module's IModule interface specification." ResourceKey="PackageName">Package Name: </Label>
<div class="col-sm-9">
@if (!string.IsNullOrEmpty(_packagename))
{
<div class="input-group">
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
@if (string.IsNullOrEmpty(_packageurl))
{
<button type="button" class="btn btn-secondary" @onclick="ValidatePackage">@Localizer["Validate"]</button>
}
else
{
<a href="@_packageurl" target="_blank" class="btn btn-primary">@SharedLocalizer["Download"]</a>
}
</div>
}
else
{
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
}
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
@@ -90,7 +73,7 @@
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="url" HelpText="The reference url of the module" ResourceKey="ReferenceUrl">Reference Url: </Label>
<Label Class="col-sm-3" For="url" HelpText="The url of the module" ResourceKey="Url">Url: </Label>
<div class="col-sm-9">
<input id="url" class="form-control" @bind="@_url" disabled />
</div>
@@ -244,7 +227,6 @@
private string _moduledefinitionname = "";
private string _version;
private string _packagename = "";
private string _packageurl = "";
private string _owner = "";
private string _url = "";
private string _contact = "";
@@ -254,11 +236,10 @@
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
private List<Page> _pagesWithModules;
#pragma warning disable 649
private PermissionGrid _permissionGrid;
#pragma warning restore 649
private List<Page> _pagesWithModules;
private List<Package> _packages;
private List<Language> _languages;
@@ -307,13 +288,15 @@
}
// get distinct pages where module exists
var distinctPageIds = PageState.Modules
var modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId);
var distinctPageIds = modules
.Where(md => md.ModuleDefinition?.ModuleDefinitionId == _moduleDefinitionId && md.IsDeleted == false)
.Select(md => md.PageId)
.Distinct();
// Filter and retrieve the corresponding pages
_pagesWithModules = PageState.Pages
// retrieve the pages which contain the module
var pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
_pagesWithModules = pages
.Where(pg => distinctPageIds.Contains(pg.PageId) && pg.IsDeleted == false)
.ToList();
@@ -443,27 +426,5 @@
}
}
private async Task ValidatePackage()
{
try
{
var package = await PackageService.GetPackageAsync(_packagename, _version, true);
if (package == null || string.IsNullOrEmpty(package.PackageUrl))
{
AddModuleMessage(Localizer["Message.Validate"], MessageType.Warning);
}
else
{
_packageurl = package.PackageUrl;
AddModuleMessage(Localizer["Message.Download"], MessageType.Info);
}
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packagename, _version);
AddModuleMessage(Localizer["Error.Validate"], MessageType.Error);
}
}
private string Browse(Page page) => string.IsNullOrEmpty(page.Url) ? NavigateUrl(page.Path) : page.Url;
}

View File

@@ -1,6 +1,7 @@
@namespace Oqtane.Modules.Admin.ModuleDefinitions
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IModuleService ModuleService
@inject IModuleDefinitionService ModuleDefinitionService
@inject IPackageService PackageService
@inject IStringLocalizer<Index> Localizer
@@ -12,32 +13,32 @@
}
else
{
<div class="container">
<div class="row mb-3 align-items-center">
<div class="col-sm-6">
<ActionLink Action="Add" Text="Install Module" ResourceKey="InstallModule" />
@((MarkupString)"&nbsp;")
<ActionLink Action="Create" Text="Create Module" ResourceKey="CreateModule" Class="btn btn-secondary" />
</div>
<div class="col-sm-6">
<select class="form-select" @onchange="(e => CategoryChanged(e))">
@foreach (var category in _categories)
{
if (category == _category)
{
<option value="@category" selected>@category @Localizer["Modules"]</option>
}
else
{
<option value="@category">@category @Localizer["Modules"]</option>
}
}
</select>
</div>
</div>
</div>
<Pager Items="@_moduleDefinitions">
<div class="container">
<div class="row mb-3 align-items-center">
<div class="col-sm-6">
<ActionLink Action="Add" Text="Install Module" ResourceKey="InstallModule" />
<ActionLink Action="Create" Text="Create Module" ResourceKey="CreateModule" Class="btn btn-secondary ms-1" />
<button type="button" class="btn btn-secondary ms-1" @onclick="@Synchronize">@Localizer["Synchronize"]</button>
</div>
<div class="col-sm-6">
<select class="form-select" @onchange="(e => CategoryChanged(e))">
@foreach (var category in _categories)
{
if (category == _category)
{
<option value="@category" selected>@category @Localizer["Modules"]</option>
}
else
{
<option value="@category">@category @Localizer["Modules"]</option>
}
}
</select>
</div>
</div>
</div>
<Pager Items="@_moduleDefinitions">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
@@ -60,17 +61,17 @@ else
<td>@context.Name</td>
<td>@context.Version</td>
<td>
@if (context.IsEnabled)
{
<span>@SharedLocalizer["Yes"]</span>
}
else
{
<span>@SharedLocalizer["No"]</span>
}
@if (context.IsEnabled)
{
<span>@SharedLocalizer["Yes"]</span>
}
else
{
<span>@SharedLocalizer["No"]</span>
}
</td>
<td>
@if (context.AssemblyName == Constants.ClientId || PageState.Modules.Where(m => m.ModuleDefinition?.ModuleDefinitionId == context.ModuleDefinitionId).FirstOrDefault() != null)
@if (context.AssemblyName == Constants.ClientId || _modules.Where(m => m.ModuleDefinition?.ModuleDefinitionId == context.ModuleDefinitionId).FirstOrDefault() != null)
{
<span>@SharedLocalizer["Yes"]</span>
}
@@ -86,9 +87,9 @@ else
@((MarkupString)PurchaseLink(context.PackageName))
</td>
<td>
@{
var version = UpgradeAvailable(context.PackageName, context.Version);
}
@{
var version = UpgradeAvailable(context.PackageName, context.Version);
}
@if (version != context.Version)
{
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadModule(context.PackageName, version))>@SharedLocalizer["Upgrade"]</button>
@@ -99,6 +100,7 @@ else
}
@code {
private List<Module> _modules;
private List<ModuleDefinition> _allModuleDefinitions;
private List<ModuleDefinition> _moduleDefinitions;
private List<Package> _packages;
@@ -111,6 +113,7 @@ else
{
try
{
_modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId);
_allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
_categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList();
await LoadModuleDefinitions();
@@ -150,10 +153,10 @@ else
link = "<a class=\"btn btn-primary\" style=\"text-decoration: none !important\" href=\"" + package.PaymentUrl + "\" target=\"_new\">" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + "</a>";
}
}
}
}
return link;
}
}
}
return link;
}
private string SupportLink(string packagename, string version)
{
@@ -169,52 +172,75 @@ else
return link;
}
private string UpgradeAvailable(string packagename, string version)
{
if (!string.IsNullOrEmpty(packagename) && _packages != null)
{
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
if (package != null && Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0)
{
return package.Version;
}
}
return version;
}
private string UpgradeAvailable(string packagename, string version)
{
if (!string.IsNullOrEmpty(packagename) && _packages != null)
{
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
if (package != null && Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0)
{
return package.Version;
}
}
return version;
}
private async Task DownloadModule(string packagename, string version)
{
try
{
await PackageService.DownloadPackageAsync(packagename, version);
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", packagename, version);
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version} {Error}", packagename, version, ex.Message);
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
}
}
private async Task DownloadModule(string packagename, string version)
{
try
{
await PackageService.DownloadPackageAsync(packagename, version);
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", packagename, version);
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version} {Error}", packagename, version, ex.Message);
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
}
}
private async Task DeleteModule(ModuleDefinition moduleDefinition)
{
try
{
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
AddModuleMessage(Localizer["Success.Module.Delete"], MessageType.Success);
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, true));
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Module {ModuleDefinition} {Error}", moduleDefinition, ex.Message);
AddModuleMessage(Localizer["Error.Module.Delete"], MessageType.Error);
}
}
private async Task DeleteModule(ModuleDefinition moduleDefinition)
{
try
{
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
AddModuleMessage(Localizer["Success.Module.Delete"], MessageType.Success);
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, true));
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Module {ModuleDefinition} {Error}", moduleDefinition, ex.Message);
AddModuleMessage(Localizer["Error.Module.Delete"], MessageType.Error);
}
}
private async Task CategoryChanged(ChangeEventArgs e)
{
_category = (string)e.Value;
private async Task CategoryChanged(ChangeEventArgs e)
{
_category = (string)e.Value;
await LoadModuleDefinitions();
}
}
private async Task Synchronize()
{
try
{
ShowProgressIndicator();
foreach (var moduleDefinition in _moduleDefinitions)
{
if (!string.IsNullOrEmpty(moduleDefinition.PackageName) && !_packages.Any(item => item.PackageId == moduleDefinition.PackageName))
{
var package = await PackageService.GetPackageAsync(moduleDefinition.PackageName, moduleDefinition.Version, false);
}
}
HideProgressIndicator();
AddModuleMessage(Localizer["Success.Module.Synchronize"], MessageType.Success);
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, true));
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Synchronizing Modules {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Module.Synchronize"], MessageType.Error);
}
}
}

View File

@@ -5,24 +5,57 @@
@inject IStringLocalizer<Export> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="content" HelpText="The Exported Module Content" ResourceKey="Content">Content: </Label>
<div class="col-sm-9">
<textarea id="content" class="form-control" @bind="@_content" rows="5" readonly></textarea>
<TabStrip>
<TabPanel Name="Content" Heading="Content" ResourceKey="Content">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="content" HelpText="Select the Export option and you will be able to view the module content" ResourceKey="Content">Content: </Label>
<div class="col-sm-9">
<textarea id="content" class="form-control" @bind="@_content" rows="5" readonly></textarea>
</div>
</div>
</div>
</div>
</div>
<br />
<button type="button" class="btn btn-success" @onclick="ExportText">@Localizer["Export"]</button>
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
</TabPanel>
<TabPanel Name="File" Heading="File" ResourceKey="File">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="folder" HelpText="Select a folder where you wish to save the exported content" ResourceKey="Folder">Folder: </Label>
<div class="col-sm-9">
<FileManager ShowFiles="false" ShowUpload="false" @ref="_filemanager" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="filename" HelpText="Specify a name for the file (without an extension)" ResourceKey="Filename">Filename: </Label>
<div class="col-sm-9">
<input id="content" type="text" class="form-control" @bind="@_filename" />
</div>
</div>
</div>
<br />
<button type="button" class="btn btn-success" @onclick="ExportFile">@Localizer["Export"]</button>
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
</TabPanel>
</TabStrip>
<button type="button" class="btn btn-success" @onclick="ExportModule">@Localizer["Export"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
@code {
private string _content = string.Empty;
private FileManager _filemanager;
private string _filename = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Title => "Export Content";
private async Task ExportModule()
protected override void OnInitialized()
{
_filename = Utilities.GetFriendlyUrl(ModuleState.Title);
}
private async Task ExportText()
{
try
{
@@ -35,4 +68,34 @@
AddModuleMessage(Localizer["Error.Module.Export"], MessageType.Error);
}
}
private async Task ExportFile()
{
try
{
var folderid = _filemanager.GetFolderId();
if (folderid != -1 && !string.IsNullOrEmpty(_filename))
{
var fileid = await ModuleService.ExportModuleAsync(ModuleState.ModuleId, PageState.Page.PageId, folderid, _filename);
if (fileid != -1)
{
AddModuleMessage(Localizer["Success.Content.Export"], MessageType.Success);
}
else
{
AddModuleMessage(Localizer["Error.Module.Export"], MessageType.Error);
}
}
else
{
AddModuleMessage(Localizer["Message.Content.Export"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Exporting Module {ModuleId} {Error}", ModuleState.ModuleId, ex.Message);
AddModuleMessage(Localizer["Error.Module.Export"], MessageType.Error);
}
}
}

View File

@@ -2,22 +2,29 @@
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IModuleService ModuleService
@inject IFileService FileService
@inject IStringLocalizer<Import> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="content" HelpText="Enter The Module Content To Import" ResourceKey="Content">Content: </Label>
<Label Class="col-sm-3" For="file" HelpText="Optionally upload or select a file to import for this module" ResourceKey="File">File: </Label>
<div class="col-sm-9">
<FileManager Filter="json" OnSelectFile="OnSelectFile" />
</div>
</div>
<hr />
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="content" HelpText="Provide the module content to import" ResourceKey="Content">Content: </Label>
<div class="col-sm-9">
<textarea id="content" class="form-control" @bind="@_content" rows="5" required></textarea>
</div>
</div>
</div>
<br />
<button type="button" class="btn btn-success" @onclick="ImportModule">@Localizer["Import"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
</form>
@code {
@@ -28,6 +35,12 @@
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Title => "Import Content";
private async Task OnSelectFile(int fileId)
{
var bytes = await FileService.DownloadFileAsync(fileId);
_content = System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length);
}
private async Task ImportModule()
{
validated = true;

View File

@@ -3,132 +3,156 @@
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IThemeService ThemeService
@inject IPageService PageService
@inject IModuleService ModuleService
@inject IPageModuleService PageModuleService
@inject IStringLocalizer<Settings> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<TabStrip>
<TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings">
@if (_containers != null)
{
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="module" HelpText="The name of the module" ResourceKey="Module">Module: </Label>
<div class="col-sm-9">
<input id="module" type="text" class="form-control" @bind="@_module" disabled />
@if (_initialized)
{
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<TabStrip ActiveTab="@_activetab">
<TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings">
@if (_containers != null)
{
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="module" HelpText="The name of the module" ResourceKey="Module">Module: </Label>
<div class="col-sm-9">
<input id="module" type="text" class="form-control" @bind="@_module" disabled />
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="title" HelpText="Enter the title of the module" ResourceKey="Title">Title: </Label>
<div class="col-sm-9">
<input id="title" type="text" class="form-control" @bind="@_title" required />
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="title" HelpText="Enter the title of the module" ResourceKey="Title">Title: </Label>
<div class="col-sm-9">
<input id="title" type="text" class="form-control" @bind="@_title" required />
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="pane" HelpText="The pane where the module will be displayed" ResourceKey="Pane">Pane: </Label>
<div class="col-sm-9">
<select class="form-select" @bind="@_pane">
@foreach (string pane in PageState.Page.Panes)
{
<option value="@pane">@pane Pane</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="container" HelpText="Select the module's container" ResourceKey="Container">Container: </Label>
<div class="col-sm-9">
<select id="container" class="form-select" @bind="@_containerType" required>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this module is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this module expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label>
<div class="col-sm-9">
<select id="allpages" class="form-select" @bind="@_allPages" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label>
<div class="col-sm-9">
<select id="page" class="form-select" @bind="@_pageId" required>
@if (PageState.Page.UserId != null)
{
<option value="@PageState.Page.PageId">@(PageState.Page.Name)</option>
}
else
{
foreach (Page p in PageState.Pages)
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="pane" HelpText="The pane where the module will be displayed" ResourceKey="Pane">Pane: </Label>
<div class="col-sm-9">
<select class="form-select" @bind="@_pane">
@foreach (string pane in PageState.Page.Panes)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, p.PermissionList))
<option value="@pane">@pane Pane</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="container" HelpText="Select the module's container" ResourceKey="Container">Container: </Label>
<div class="col-sm-9">
<select id="container" class="form-select" @bind="@_containerType" required>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this module is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this module expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label>
<div class="col-sm-9">
<select id="allpages" class="form-select" @bind="@_allPages" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label>
<div class="col-sm-9">
<select id="page" class="form-select" @bind="@_pageId" required>
@if (PageState.Page.UserId != null)
{
<option value="@PageState.Page.PageId">@(PageState.Page.Name)</option>
}
else
{
if (_pages != null)
{
<option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option>
foreach (Page p in _pages)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, p.PermissionList))
{
<option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option>
}
}
}
}
}
</select>
</select>
</div>
</div>
</div>
</div>
}
</TabPanel>
<TabPanel Name="Permissions" Heading="Permissions" ResourceKey="Permissions">
@if (_permissions != null)
{
<div class="container">
<div class="row mb-1 align-items-center">
<PermissionGrid EntityName="@EntityNames.Module" PermissionNames="@_permissionNames" PermissionList="@_permissions" @ref="_permissionGrid" />
<br />
<Section Name="ModuleContent" Heading="Content" ResourceKey="ModuleContent">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="moduleheader" HelpText="Optionally provide content to be injected above the module instance" ResourceKey="Header">Header: </Label>
<div class="col-sm-9">
<textarea id="moduleheader" class="form-control" @bind="@_header" rows="3" maxlength="4000"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="modulefooter" HelpText="Optionally provide content to be injected below the module instance" ResourceKey="Footer">Footer: </Label>
<div class="col-sm-9">
<textarea id="modulefooter" class="form-control" @bind="@_footer" rows="3" maxlength="4000"></textarea>
</div>
</div>
</div>
</Section>
}
</TabPanel>
<TabPanel Name="Permissions" Heading="Permissions" ResourceKey="Permissions">
@if (_permissions != null)
{
<div class="container">
<div class="row mb-1 align-items-center">
<PermissionGrid EntityName="@EntityNames.Module" PermissionNames="@_permissionNames" PermissionList="@_permissions" @ref="_permissionGrid" />
</div>
</div>
</div>
}
</TabPanel>
@if (_moduleSettingsType != null)
{
<TabPanel Name="ModuleSettings" Heading="@_moduleSettingsTitle" ResourceKey="ModuleSettings">
@ModuleSettingsComponent
</TabPanel>
}
</TabPanel>
@if (_moduleSettingsType != null)
{
<TabPanel Name="ModuleSettings" Heading="@_moduleSettingsTitle" ResourceKey="ModuleSettings">
@ModuleSettingsComponent
</TabPanel>
}
@if (_containerSettingsType != null)
{
<TabPanel Name="ContainerSettings" Heading="Container Settings" ResourceKey="ContainerSettings">
@ContainerSettingsComponent
</TabPanel>
}
</TabStrip>
<br />
<button type="button" class="btn btn-success" @onclick="SaveModule">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
<br />
<br />
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
</form>
@if (_containerSettingsType != null)
{
<TabPanel Name="ContainerSettings" Heading="Container Settings" ResourceKey="ContainerSettings">
@ContainerSettingsComponent
</TabPanel>
}
</TabStrip>
<br />
<button type="button" class="btn btn-success" @onclick="SaveModule">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
<br />
<br />
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
</form>
}
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
private bool _initialized = false;
private ElementReference form;
private bool validated = false;
private List<ThemeControl> _containers = new List<ThemeControl>();
@@ -137,6 +161,8 @@
private string _pane;
private string _containerType;
private string _allPages = "false";
private string _header = "";
private string _footer = "";
private string _permissionNames = "";
private List<Permission> _permissions = null;
private string _pageId;
@@ -154,40 +180,53 @@
private DateTime modifiedon;
private DateTime? _effectivedate = null;
private DateTime? _expirydate = null;
private List<Page> _pages;
private string _activetab = "";
protected override void OnInitialized()
protected override async Task OnInitializedAsync()
{
SetModuleTitle(Localizer["ModuleSettings.Title"]);
_module = ModuleState.ModuleDefinition.Name;
_title = ModuleState.Title;
_moduleSettingsTitle = Localizer["ModuleSettings.Heading"];
_pane = ModuleState.Pane;
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, PageState.Page.ThemeType);
_containerType = ModuleState.ContainerType;
_allPages = ModuleState.AllPages.ToString();
_permissions = ModuleState.PermissionList;
_pageId = ModuleState.PageId.ToString();
createdby = ModuleState.CreatedBy;
createdon = ModuleState.CreatedOn;
modifiedby = ModuleState.ModifiedBy;
modifiedon = ModuleState.ModifiedOn;
_effectivedate = Utilities.UtcAsLocalDate(ModuleState.EffectiveDate);
_expirydate = Utilities.UtcAsLocalDate(ModuleState.ExpiryDate);
if (ModuleState.ModuleDefinition != null)
{
_permissionNames = ModuleState.ModuleDefinition?.PermissionNames;
if (!string.IsNullOrEmpty(ModuleState.ModuleDefinition.SettingsType))
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, PageState.Page.ThemeType);
_pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
_pageId = pagemodule.PageId.ToString();
_title = pagemodule.Title;
_pane = pagemodule.Pane;
_containerType = pagemodule.ContainerType;
if (string.IsNullOrEmpty(_containerType))
{
_containerType = (!string.IsNullOrEmpty(PageState.Page.DefaultContainerType)) ? PageState.Page.DefaultContainerType : PageState.Site.DefaultContainerType;
}
_header = pagemodule.Header;
_footer = pagemodule.Footer;
_effectivedate = Utilities.UtcAsLocalDate(pagemodule.EffectiveDate);
_expirydate = Utilities.UtcAsLocalDate(pagemodule.ExpiryDate);
_allPages = pagemodule.Module.AllPages.ToString();
createdby = pagemodule.Module.CreatedBy;
createdon = pagemodule.Module.CreatedOn;
modifiedby = pagemodule.Module.ModifiedBy;
modifiedon = pagemodule.Module.ModifiedOn;
_permissions = pagemodule.Module.PermissionList;
if (pagemodule.Module.ModuleDefinition != null)
{
_module = pagemodule.Module.ModuleDefinition.Name;
_permissionNames = pagemodule.Module.ModuleDefinition?.PermissionNames;
if (!string.IsNullOrEmpty(pagemodule.Module.ModuleDefinition.SettingsType))
{
// module settings type explicitly declared in IModule interface
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.SettingsType);
_moduleSettingsType = Type.GetType(pagemodule.Module.ModuleDefinition.SettingsType);
}
else
{
// legacy support - module settings type determined by convention ( ie. existence of a "Settings.razor" component in module )
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
_moduleSettingsType = Type.GetType(pagemodule.Module.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
}
if (_moduleSettingsType != null)
{
@@ -208,7 +247,7 @@
}
else
{
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], ModuleState.ModuleDefinitionName), MessageType.Error);
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], pagemodule.Module.ModuleDefinitionName), MessageType.Error);
}
var theme = PageState.Site.Themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
@@ -226,10 +265,13 @@
};
}
}
_initialized = true;
}
private async Task SaveModule()
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
@@ -250,21 +292,23 @@
pagemodule.ExpiryDate = Utilities.LocalDateAndTimeAsUtc(_expirydate);
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);
{
pagemodule.ContainerType = string.Empty;
}
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
{
pagemodule.ContainerType = string.Empty;
}
pagemodule.Header = _header;
pagemodule.Footer = _footer;
await PageModuleService.UpdatePageModuleAsync(pagemodule);
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
var module = ModuleState;
module.AllPages = bool.Parse(_allPages);
module.PageModuleId = ModuleState.PageModuleId;
module.PermissionList = _permissionGrid.GetPermissionList();
await ModuleService.UpdateModuleAsync(module);
var module = await ModuleService.GetModuleAsync(ModuleState.ModuleId);
module.AllPages = bool.Parse(_allPages);
module.PageModuleId = ModuleState.PageModuleId;
module.PermissionList = _permissionGrid.GetPermissionList();
await ModuleService.UpdateModuleAsync(module);
if (_moduleSettingsType != null)
{
@@ -289,11 +333,13 @@
}
else
{
_activetab = "Settings";
AddModuleMessage(Localizer["Message.Required.Title"], MessageType.Warning);
}
}
else
{
_activetab = "Settings";
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
}
}

View File

@@ -16,7 +16,7 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" required />
<input id="name" class="form-control" @bind="@_name" maxlength="100" required />
</div>
</div>
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
@@ -26,7 +26,7 @@
<div class="col-sm-9">
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
<option value="-1">&lt;@Localizer["SiteRoot"]&gt;</option>
@foreach (Page page in PageState.Pages)
@foreach (Page page in _pages)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList))
{
@@ -81,54 +81,21 @@
</div>
}
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
<div class="col-sm-9">
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
<div class="col-sm-9">
<select id="clickable" class="form-select" @bind="@_isclickable" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
<input id="title" class="form-control" @bind="@_title" maxlength="200" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'." ResourceKey="UrlPath">Url Path: </Label>
<div class="col-sm-9">
<input id="path" class="form-control" @bind="@_path" />
<input id="path" class="form-control" @bind="@_path" maxlength="256" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
<div class="col-sm-9">
<input id="url" class="form-control" @bind="@_url" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
<div class="col-sm-8">
<InputList Value="@_icon" ValueChanged="IconChanged" DataList="@_icons" ResourceKey="Icon" ResourceType="@_iconresources" />
</div>
<div class="col-sm-1">
<i class="@_icon"></i>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this page is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this page expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
<input id="url" class="form-control" @bind="@_url" maxlength="500" />
</div>
</div>
<div class="row mb-1 align-items-center">
@@ -141,22 +108,22 @@
</div>
</div>
</div>
<Section Name="Appearance" ResourceKey="Appearance" Heading=@Localizer["Appearance.Name"]>
<Section Name="Theme" Heading="Theme" ResourceKey="Theme">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
<div class="col-sm-9">
<input id="title" class="form-control" @bind="@_title" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
<div class="col-sm-9">
<select id="theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
@foreach (var theme in _themes)
{
<option value="@theme.TypeName">@theme.Name</option>
@if (theme.TypeName == PageState.Site.DefaultThemeType)
{
<option value="@theme.TypeName">*@theme.Name*</option>
}
else
{
<option value="@theme.TypeName">@theme.Name</option>
}
}
</select>
</div>
@@ -174,18 +141,61 @@
</div>
</div>
</Section>
<Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
<div class="col-sm-8">
<InputList Value="@_icon" ValueChanged="IconChanged" DataList="@_icons" ResourceKey="Icon" ResourceType="@_iconresources" />
</div>
<div class="col-sm-1">
<i class="@_icon"></i>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
<div class="col-sm-9">
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
<div class="col-sm-9">
<select id="clickable" class="form-select" @bind="@_isclickable" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this page is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this page expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
</div>
</div>
</div>
</Section>
<Section Name="PageContent" ResourceKey="PageContent" Heading=@Localizer["PageContent.Heading"]>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta, link, or script tags)" ResourceKey="HeadContent">Head Content: </Label>
<div class="col-sm-9">
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3" maxlength="4000"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="bodycontent" HelpText="Optionally enter content to be included in the page body (ie. script tags)" ResourceKey="BodyContent">Body Content: </Label>
<div class="col-sm-9">
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3"></textarea>
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3" maxlength="4000"></textarea>
</div>
</div>
</div>
@@ -213,6 +223,7 @@
private bool validated = false;
private List<ThemeControl> _themes = new List<ThemeControl>();
private List<ThemeControl> _containers = new List<ThemeControl>();
private List<Page> _pages;
private int _pageId;
private string _name;
private string _parentid = "-1";
@@ -243,6 +254,8 @@
{
try
{
_pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
if (PageState.QueryString.ContainsKey("id"))
{
_pageId = Int32.Parse(PageState.QueryString["id"]);
@@ -259,11 +272,19 @@
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin) || (_parent != null && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, _parent.PermissionList)))
{
_themetype = PageState.Site.DefaultThemeType;
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
var themes = new List<Theme>();
foreach (var theme in PageState.Site.Themes)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, theme.PermissionList))
{
themes.Add(theme);
}
}
_themes = ThemeService.GetThemeControls(themes);
_containers = ThemeService.GetContainerControls(themes, _themetype);
_containertype = PageState.Site.DefaultContainerType;
_children = new List<Page>();
foreach (Page p in PageState.Pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid))))
foreach (Page p in _pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid))))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
{
@@ -293,7 +314,7 @@
{
_parentid = (string)e.Value;
_children = new List<Page>();
foreach (Page p in PageState.Pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid))))
foreach (Page p in _pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid))))
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
{
@@ -306,10 +327,11 @@
{
await logger.LogError(ex, "Error Loading Child Pages For Parent {PageId} {Error}", _parentid, ex.Message);
AddModuleMessage(Localizer["Error.ChildPage.Load"], MessageType.Error);
await ScrollToPageTop();
}
}
private void ThemeChanged(ChangeEventArgs e)
private async Task ThemeChanged(ChangeEventArgs e)
{
_themetype = (string)e.Value;
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
@@ -320,6 +342,7 @@
if (ThemeService.GetTheme(PageState.Site.Themes, _themetype)?.ThemeName != ThemeService.GetTheme(PageState.Site.Themes, PageState.Site.DefaultThemeType)?.ThemeName)
{
AddModuleMessage(Localizer["ThemeChanged.Message"], MessageType.Warning);
await ScrollToPageTop();
}
}
@@ -335,6 +358,7 @@
if (!Utilities.ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
{
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
await ScrollToPageTop();
return;
}
if (!string.IsNullOrEmpty(_themetype) && !string.IsNullOrEmpty(_containertype))
@@ -371,7 +395,7 @@
}
else
{
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId);
Page parent = _pages.FirstOrDefault(item => item.PageId == page.ParentId);
if (parent.Path == string.Empty)
{
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
@@ -382,16 +406,17 @@
}
}
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
if (_pages.Any(item => item.Path == page.Path))
{
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
await ScrollToPageTop();
return;
}
if (page.ParentId == null && Constants.ReservedRoutes.Contains(page.Name.ToLower()))
{
AddModuleMessage(string.Format(Localizer["Message.Page.Reserved"], page.Name), MessageType.Warning);
await ScrollToPageTop();
return;
}
@@ -402,11 +427,11 @@
page.Order = 0;
break;
case "<":
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
child = _pages.Where(item => item.PageId == _childid).FirstOrDefault();
page.Order = child.Order - 1;
break;
case ">":
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
child = _pages.Where(item => item.PageId == _childid).FirstOrDefault();
page.Order = child.Order + 1;
break;
case ">>":
@@ -449,7 +474,7 @@
await logger.LogInformation("Page Added {Page}", page);
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
{
NavigationManager.NavigateTo(page.Path, true); // redirect to page added and reload
NavigationManager.NavigateTo(NavigateUrl(page.Path), true); // redirect to page added and reload
}
else
{
@@ -459,6 +484,7 @@
else
{
AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning);
await ScrollToPageTop();
}
}
@@ -466,11 +492,13 @@
{
await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message);
AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error);
await ScrollToPageTop();
}
}
else
{
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
await ScrollToPageTop();
}
}

View File

@@ -5,7 +5,8 @@
@inject NavigationManager NavigationManager
@inject IPageService PageService
@inject IPageModuleService PageModuleService
@inject IThemeService ThemeService
@inject IModuleService ModuleService
@inject IThemeService ThemeService
@inject ISystemService SystemService
@inject IStringLocalizer<Edit> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@@ -21,7 +22,7 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" maxlength="50" required />
<input id="name" class="form-control" @bind="@_name" maxlength="100" required />
</div>
</div>
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
@@ -29,16 +30,16 @@
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
<div class="col-sm-9">
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
<option value="-1">&lt;@Localizer["SiteRoot"]&gt;</option>
@foreach (Page page in PageState.Pages)
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
<option value="-1">&lt;@Localizer["SiteRoot"]&gt;</option>
@foreach (Page page in _pages)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList) && page.PageId != _pageId)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList) && page.PageId != _pageId)
{
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
}
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
}
</select>
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
@@ -97,25 +98,13 @@
</div>
}
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
<div class="col-sm-9">
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
<input id="title" class="form-control" @bind="@_title" maxlength="200" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
<div class="col-sm-9">
<select id="clickable" class="form-select" @bind="@_isclickable" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. If the page is intended to be the root path specify '/'." ResourceKey="UrlPath">Url Path: </Label>
<Label Class="col-sm-3" For="path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used. Please note that spaces and punctuation will be replaced by a dash. If the page is intended to be the root path specify '/'." ResourceKey="UrlPath">Url Path: </Label>
<div class="col-sm-9">
<input id="path" class="form-control" @bind="@_path" maxlength="256" />
</div>
@@ -126,27 +115,6 @@
<input id="url" class="form-control" @bind="@_url" maxlength="500" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
<div class="col-sm-8">
<InputList Value="@_icon" ValueChanged="IconChanged" DataList="@_icons" ResourceKey="Icon" ResourceType="@_iconresources" />
</div>
<div class="col-sm-1">
<i class="@_icon"></i>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this page is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this page expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
<div class="col-sm-9">
@@ -157,21 +125,22 @@
</div>
</div>
</div>
<Section Name="Appearance" ResourceKey="Appearance" Heading="Appearance">
<Section Name="Theme" ResourceKey="Theme" Heading="Theme">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
<div class="col-sm-9">
<input id="title" class="form-control" @bind="@_title" maxlength="200" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
<div class="col-sm-9">
<select id="theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
@foreach (var theme in _themes)
{
<option value="@theme.TypeName">@theme.Name</option>
@if (theme.TypeName == PageState.Site.DefaultThemeType)
{
<option value="@theme.TypeName">*@theme.Name*</option>
}
else
{
<option value="@theme.TypeName">@theme.Name</option>
}
}
</select>
</div>
@@ -192,23 +161,69 @@
</div>
</div>
</Section>
<Section Name="Appearance" ResourceKey="Appearance" Heading="Appearance">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
<div class="col-sm-8">
<InputList Value="@_icon" ValueChanged="IconChanged" DataList="@_icons" ResourceKey="Icon" ResourceType="@_iconresources" />
</div>
<div class="col-sm-1">
<i class="@_icon"></i>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
<div class="col-sm-9">
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
<div class="col-sm-9">
<select id="clickable" class="form-select" @bind="@_isclickable" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this page is active" ResourceKey="EffectiveDate">Effective Date: </Label>
<div class="col-sm-9">
<input type="date" id="effectiveDate" class="form-control" @bind="@_effectivedate" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this page expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
<div class="col-sm-9">
<input type="date" id="expiryDate" class="form-control" @bind="@_expirydate" />
</div>
</div>
</div>
</Section>
<Section Name="PageContent" Heading="Page Content" ResourceKey="PageContent">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta, link, or script tags)" ResourceKey="HeadContent">Head Content: </Label>
<div class="col-sm-9">
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3" maxlength="4000"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="bodycontent" HelpText="Optionally enter content to be included in the page body (ie. script tags)" ResourceKey="BodyContent">Body Content: </Label>
<div class="col-sm-9">
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3"></textarea>
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3" maxlength="4000"></textarea>
</div>
</div>
</div>
</Section>
<br />
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
<br />
<br />
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
</TabPanel>
@@ -217,15 +232,28 @@
<div class="row mb-1 align-items-center">
<PermissionGrid EntityName="@EntityNames.Page" PermissionList="@_permissions" @ref="_permissionGrid" />
</div>
<br /><br />
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="updatemodulepermissions" HelpText="Specify if changes made to page permissions should be propagated to the modules on this page" ResourceKey="UpdateModulePermissions">Update Module Permissions? </Label>
<div class="col-sm-9">
<select id="updatemodulepermissions" class="form-select" @bind="@_updatemodulepermissions" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<br />
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
</div>
</TabPanel>
<TabPanel Name="PageModules" Heading="Modules" ResourceKey="PageModules">
<Pager Items="_pageModules">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@Localizer["ModuleTitle"]</th>
<th>@Localizer["ModuleDefinition"]</th>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@Localizer["ModuleTitle"]</th>
<th>@Localizer["ModuleDefinition"]</th>
</Header>
<Row>
<td><ActionLink Action="Settings" Text="Edit" Path="@_actualpath" ModuleId="@context.ModuleId" Security="SecurityAccessLevel.Edit" PermissionList="@context.PermissionList" ResourceKey="ModuleSettings" /></td>
@@ -239,8 +267,10 @@
{
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
@_themeSettingsComponent
<br />
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
</TabPanel>
<br />
}
</TabStrip>
}
@@ -255,13 +285,26 @@
<input id="title" class="form-control" @bind="@_title" maxlength="200" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="path" HelpText="Provide a url path for your personalized page. Please note that spaces and punctuation will be replaced by a dash." ResourceKey="PersonalizedUrlPath">Url Path: </Label>
<div class="col-sm-9">
<input id="path" class="form-control" @bind="@_path" maxlength="256" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
<div class="col-sm-9">
<select id="theme" class="form-select" @bind="@_themetype" required>
@foreach (var theme in _themes)
{
<option value="@theme.TypeName">@theme.Name</option>
@if (theme.TypeName == PageState.Site.DefaultThemeType)
{
<option value="@theme.TypeName">*@theme.Name*</option>
}
else
{
<option value="@theme.TypeName">@theme.Name</option>
}
}
</select>
</div>
@@ -278,19 +321,21 @@
</div>
</div>
</div>
<br />
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
</TabPanel>
@if (_themeSettingsType != null)
{
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
@_themeSettingsComponent
<br />
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
</TabPanel>
<br />
}
</TabStrip>
}
<br />
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
</form>
}
@@ -302,6 +347,7 @@
private bool validated = false;
private List<ThemeControl> _themes = new List<ThemeControl>();
private List<ThemeControl> _containers = new List<ThemeControl>();
private List<Page> _pages;
private int _pageId;
private string _name;
private string _currentparentid;
@@ -326,6 +372,7 @@
private string _bodycontent;
private List<Permission> _permissions = null;
private PermissionGrid _permissionGrid;
private string _updatemodulepermissions;
private List<Module> _pageModules;
private string _createdby;
private DateTime _createdon;
@@ -345,6 +392,7 @@
{
try
{
_pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
_pageId = Int32.Parse(PageState.QueryString["id"]);
_page = await PageService.GetPageAsync(_pageId);
_icons = await SystemService.GetIconsAsync();
@@ -360,10 +408,10 @@
else
{
_parentid = _page.ParentId.ToString();
_parent = PageState.Pages.FirstOrDefault(item => item.PageId == _page.ParentId);
_parent = _pages.FirstOrDefault(item => item.PageId == _page.ParentId);
}
_children = new List<Page>();
foreach (Page p in PageState.Pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid, CultureInfo.InvariantCulture))))
foreach (Page p in _pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid, CultureInfo.InvariantCulture))))
{
if (p.PageId != _pageId && UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
{
@@ -399,8 +447,16 @@
{
_themetype = PageState.Site.DefaultThemeType;
}
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
var themes = new List<Theme>();
foreach (var theme in PageState.Site.Themes)
{
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, theme.PermissionList))
{
themes.Add(theme);
}
}
_themes = ThemeService.GetThemeControls(themes);
_containers = ThemeService.GetContainerControls(themes, _themetype);
_containertype = _page.DefaultContainerType;
if (string.IsNullOrEmpty(_containertype))
{
@@ -413,9 +469,11 @@
// permissions
_permissions = _page.PermissionList;
_updatemodulepermissions = "True";
// page modules
_pageModules = PageState.Modules.Where(m => m.PageId == _page.PageId).ToList();
var modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId);
_pageModules = modules.Where(item => item.PageId == _page.PageId && !item.IsDeleted).ToList();
// audit
_createdby = _page.CreatedBy;
@@ -447,7 +505,7 @@
{
_parentid = (string)e.Value;
_children = new List<Page>();
foreach (Page p in PageState.Pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid))))
foreach (Page p in _pages.Where(item => (_parentid == "-1" && item.ParentId == null) || (item.ParentId == int.Parse(_parentid))))
{
if (p.PageId != _pageId && UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
{
@@ -461,10 +519,11 @@
{
await logger.LogError(ex, "Error Loading Child Pages For Parent {PageId} {Error}", _parentid, ex.Message);
AddModuleMessage(Localizer["Error.ChildPage.Load"], MessageType.Error);
await ScrollToPageTop();
}
}
private void ThemeChanged(ChangeEventArgs e)
private async Task ThemeChanged(ChangeEventArgs e)
{
_themetype = (string)e.Value;
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
@@ -476,6 +535,7 @@
if (ThemeService.GetTheme(PageState.Site.Themes, _themetype)?.ThemeName != ThemeService.GetTheme(PageState.Site.Themes, PageState.Site.DefaultThemeType)?.ThemeName)
{
AddModuleMessage(Localizer["ThemeChanged.Message"], MessageType.Warning);
await ScrollToPageTop();
}
}
@@ -513,6 +573,7 @@
if (!Utilities.ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
{
AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
await ScrollToPageTop();
return;
}
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
@@ -549,7 +610,7 @@
}
else
{
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == _page.ParentId);
Page parent = _pages.FirstOrDefault(item => item.PageId == _page.ParentId);
if (parent.Path == string.Empty)
{
_page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
@@ -560,16 +621,17 @@
}
}
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
if (_pages.Any(item => item.Path == _page.Path && item.PageId != _page.PageId))
{
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
await ScrollToPageTop();
return;
}
if (_page.ParentId == null && Constants.ReservedRoutes.Contains(_page.Name.ToLower()))
{
AddModuleMessage(string.Format(Localizer["Message.Page.Reserved"], _page.Name), MessageType.Warning);
await ScrollToPageTop();
return;
}
@@ -582,11 +644,11 @@
_page.Order = 0;
break;
case "<":
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
child = _pages.FirstOrDefault(item => item.PageId == _childid);
if (child != null) _page.Order = child.Order - 1;
break;
case ">":
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
child = _pages.FirstOrDefault(item => item.PageId == _childid);
if (child != null) _page.Order = child.Order + 1;
break;
case ">>":
@@ -623,6 +685,7 @@
if (_page.UserId == null)
{
_page.PermissionList = _permissionGrid.GetPermissionList();
_page.UpdateModulePermissions = bool.Parse(_updatemodulepermissions);
}
_page = await PageService.UpdatePageAsync(_page);
@@ -654,17 +717,20 @@
else
{
AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning);
await ScrollToPageTop();
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Page {Page} {Error}", _page, ex.Message);
AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error);
await ScrollToPageTop();
}
}
else
{
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
await ScrollToPageTop();
}
}

View File

@@ -5,11 +5,11 @@
@inject IStringLocalizer<Index> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@if (PageState.Pages != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
@if (_pages != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
{
<ActionLink Action="Add" Text="Add Page" ResourceKey="AddPage" />
<Pager Items="@PageState.Pages.Where(item => !item.IsDeleted)" SearchProperties="Name">
<Pager Items="@_pages.Where(item => !item.IsDeleted)" SearchProperties="Name">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
@@ -28,6 +28,21 @@
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
private List<Page> _pages;
protected override async Task OnInitializedAsync()
{
try
{
_pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Pages {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Page.Load"], MessageType.Error);
}
}
private async Task DeletePage(Page page)
{
try

View File

@@ -2,6 +2,7 @@
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject IProfileService ProfileService
@inject ISettingService SettingService
@inject IStringLocalizer<Edit> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@@ -56,9 +57,25 @@
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="options" HelpText="A comma delimited list of options the user can select from" ResourceKey="Options">Options: </Label>
<Label Class="col-sm-3" For="options" HelpText="A comma delimited list of options. Options can contain a key and value if they are seperated by a colon (ie. key:value). You can also dynamically load your options from Settings." ResourceKey="Options">Options: </Label>
<div class="col-sm-9">
<input id="options" class="form-control" @bind="@_options" maxlength="2000" />
<div class="input-group">
@if (_optiontype == "Settings")
{
<input id="options" class="form-control" @bind="@_options" maxlength="2000" />
}
else
{
<select id="entityName" class="form-select" @bind="@_options">
<option value="">&lt;@SharedLocalizer["Not Specified"]&gt;</option>
@foreach (var entityname in _entitynames)
{
<option value="@entityname">@entityname</option>
}
</select>
}
<button type="button" class="btn btn-secondary" @onclick="ToggleOptionType">@Localizer[_optiontype]</button>
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
@@ -95,7 +112,7 @@
<br />
<button type="button" class="btn btn-success" @onclick="SaveProfile">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
@if (PageState.QueryString.ContainsKey("id"))
@if (PageState.QueryString.ContainsKey("id"))
{
<br />
<br />
@@ -116,6 +133,8 @@
private string _rows = "1";
private string _defaultvalue = string.Empty;
private string _options = string.Empty;
private string _optiontype = "Settings";
private List<string> _entitynames;
private string _validation = string.Empty;
private string _autocomplete = string.Empty;
private string _isrequired = "False";
@@ -133,6 +152,8 @@
{
try
{
_entitynames = await SettingService.GetEntityNamesAsync();
if (PageState.QueryString.ContainsKey("id"))
{
_profileid = Int32.Parse(PageState.QueryString["id"]);
@@ -148,6 +169,11 @@
_rows = profile.Rows.ToString();
_defaultvalue = profile.DefaultValue;
_options = profile.Options;
if (_options.StartsWith("EntityName:"))
{
_optiontype = "Options";
_options = _options.Substring(11);
}
_validation = profile.Validation;
_autocomplete = profile.Autocomplete;
_isrequired = profile.IsRequired.ToString();
@@ -166,6 +192,18 @@
}
}
private void ToggleOptionType()
{
if (_optiontype == "Options")
{
_optiontype = "Settings";
}
else
{
_optiontype = "Options";
}
}
private async Task SaveProfile()
{
validated = true;
@@ -193,7 +231,14 @@
profile.MaxLength = int.Parse(_maxlength);
profile.Rows = int.Parse(_rows);
profile.DefaultValue = _defaultvalue;
profile.Options = _options;
if (_optiontype == "Options" && !string.IsNullOrEmpty(_options))
{
profile.Options = "EntityName:" + _options;
}
else
{
profile.Options = _options;
}
profile.Validation = _validation;
profile.Autocomplete = _autocomplete;
profile.IsRequired = (_isrequired == null ? false : Boolean.Parse(_isrequired));

View File

@@ -13,71 +13,71 @@
}
else
{
<TabStrip>
<TabPanel Name="Pages" ResourceKey="Pages" Heading="Pages">
@if (!_pages.Where(item => item.IsDeleted).Any())
{
<br />
<p>@Localizer["NoPage.Deleted"]</p>
}
else
{
<Pager Items="@_pages.Where(item => item.IsDeleted)" CurrentPage="@_pagePage.ToString()" OnPageChange="OnPageChangePage">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@SharedLocalizer["Name"]</th>
<th>@Localizer["DeletedBy"]</th>
<th>@Localizer["DeletedOn"]</th>
</Header>
<Row>
<TabStrip>
<TabPanel Name="Pages" ResourceKey="Pages" Heading="Pages">
@if (!_pages.Where(item => item.IsDeleted).Any())
{
<br />
<p>@Localizer["NoPage.Deleted"]</p>
}
else
{
<Pager Items="@_pages.Where(item => item.IsDeleted).OrderByDescending(item => item.DeletedOn)" CurrentPage="@_pagePage.ToString()" OnPageChange="OnPageChangePage">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@SharedLocalizer["Path"]</th>
<th>@Localizer["DeletedBy"]</th>
<th>@Localizer["DeletedOn"]</th>
</Header>
<Row>
<td><button type="button" @onclick="@(() => RestorePage(context))" class="btn btn-success" title="Restore">@Localizer["Restore"]</button></td>
<td><ActionDialog Header="Delete Page" Message="@string.Format(Localizer["Confirm.Page.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeletePage(context))" ResourceKey="DeletePage" /></td>
<td>@context.Name</td>
<td>@context.DeletedBy</td>
<td>@context.DeletedOn</td>
</Row>
</Pager>
<br />
<ActionDialog Header="Remove All Deleted Pages" Message="Are You Sure You Wish To Permanently Remove All Deleted Pages?" Action="Remove All Deleted Pages" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteAllPages())" ResourceKey="DeleteAllPages" />
}
</TabPanel>
<TabPanel Name="Modules" ResourceKey="Modules" Heading="Modules">
@if (!_modules.Where(item => item.IsDeleted).Any())
{
<br />
<p>@Localizer["NoModule.Deleted"]</p>
}
else
{
<Pager Items="@_modules.Where(item => item.IsDeleted)" CurrentPage="@_pageModule.ToString()" OnPageChange="OnPageChangeModule">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@Localizer["Page"]</th>
<th>@Localizer["Module"]</th>
<th>@Localizer["DeletedBy"]</th>
<th>@Localizer["DeletedOn"]</th>
</Header>
<Row>
<td><button type="button" @onclick="@(() => RestoreModule(context))" class="btn btn-success" title="Restore">@Localizer["Restore"]</button></td>
<td><ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete"], context.Title)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" /></td>
<td>@_pages.Find(item => item.PageId == context.PageId).Name</td>
<td>@context.Title</td>
<td>@context.DeletedBy</td>
<td>@context.DeletedOn</td>
</Row>
</Pager>
<br />
<ActionDialog Header="Remove All Deleted Modules" Message="Are You Sure You Wish To Permanently Remove All Deleted Modules?" Action="Remove All Deleted Modules" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteAllModules())" ResourceKey="DeleteAllModules" />
}
</TabPanel>
</TabStrip>
<td><ActionDialog Header="Delete Page" Message="@string.Format(Localizer["Confirm.Page.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeletePage(context))" ResourceKey="DeletePage" /></td>
<td>@context.Path</td>
<td>@context.DeletedBy</td>
<td>@context.DeletedOn</td>
</Row>
</Pager>
<br />
<ActionDialog Header="Remove All Deleted Pages" Message="Are You Sure You Wish To Permanently Remove All Deleted Pages?" Action="Remove All Deleted Pages" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteAllPages())" ResourceKey="DeleteAllPages" />
}
</TabPanel>
<TabPanel Name="Modules" ResourceKey="Modules" Heading="Modules">
@if (!_modules.Where(item => item.IsDeleted).Any())
{
<br />
<p>@Localizer["NoModule.Deleted"]</p>
}
else
{
<Pager Items="@_modules.Where(item => item.IsDeleted).OrderByDescending(item => item.DeletedOn)" CurrentPage="@_pageModule.ToString()" OnPageChange="OnPageChangeModule">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@Localizer["Page"]</th>
<th>@Localizer["Module"]</th>
<th>@Localizer["DeletedBy"]</th>
<th>@Localizer["DeletedOn"]</th>
</Header>
<Row>
<td><button type="button" @onclick="@(() => RestoreModule(context))" class="btn btn-success" title="Restore">@Localizer["Restore"]</button></td>
<td><ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete"], context.Title)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" /></td>
<td>@_pages.Find(item => item.PageId == context.PageId).Name</td>
<td>@context.Title</td>
<td>@context.DeletedBy</td>
<td>@context.DeletedOn</td>
</Row>
</Pager>
<br />
<ActionDialog Header="Remove All Deleted Modules" Message="Are You Sure You Wish To Permanently Remove All Deleted Modules?" Action="Remove All Deleted Modules" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteAllModules())" ResourceKey="DeleteAllModules" />
}
</TabPanel>
</TabStrip>
}
@code {
private List<Page> _pages;
private List<Module> _modules;
private List<Page> _pages;
private List<Module> _modules;
private int _pagePage = 1;
private int _pageModule = 1;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
@@ -105,12 +105,25 @@ else
{
try
{
page.IsDeleted = false;
await PageService.UpdatePageAsync(page);
await logger.LogInformation("Page Restored {Page}", page);
await Load();
StateHasChanged();
NavigationManager.NavigateTo(NavigateUrl());
var validated = true;
if (page.ParentId != null)
{
var parent = _pages.Find(item => item.PageId == page.ParentId);
validated = !parent.IsDeleted;
}
if (validated)
{
page.IsDeleted = false;
await PageService.UpdatePageAsync(page);
await logger.LogInformation("Page Restored {Page}", page);
AddModuleMessage(Localizer["Success.Page.Restore"], MessageType.Success);
await Load();
StateHasChanged();
}
else
{
AddModuleMessage(Localizer["Message.Page.Restore"], MessageType.Warning);
}
}
catch (Exception ex)
{
@@ -125,9 +138,9 @@ else
{
await PageService.DeletePageAsync(page.PageId);
await logger.LogInformation("Page Permanently Deleted {Page}", page);
AddModuleMessage(Localizer["Success.Page.Delete"], MessageType.Success);
await Load();
StateHasChanged();
NavigationManager.NavigateTo(NavigateUrl());
}
catch (Exception ex)
{
@@ -148,10 +161,10 @@ else
}
await logger.LogInformation("Pages Permanently Deleted");
AddModuleMessage(Localizer["Success.Pages.Delete"], MessageType.Success);
await Load();
HideProgressIndicator();
StateHasChanged();
NavigationManager.NavigateTo(NavigateUrl());
}
catch (Exception ex)
{
@@ -169,6 +182,7 @@ else
pagemodule.IsDeleted = false;
await PageModuleService.UpdatePageModuleAsync(pagemodule);
await logger.LogInformation("Module Restored {Module}", module);
AddModuleMessage(Localizer["Success.Module.Restore"], MessageType.Success);
await Load();
StateHasChanged();
}
@@ -185,6 +199,7 @@ else
{
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
await logger.LogInformation("Module Permanently Deleted {Module}", module);
AddModuleMessage(Localizer["Success.Module.Delete"], MessageType.Success);
await Load();
StateHasChanged();
}
@@ -205,6 +220,7 @@ else
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
}
await logger.LogInformation("Modules Permanently Deleted");
AddModuleMessage(Localizer["Success.Modules.Delete"], MessageType.Success);
await Load();
HideProgressIndicator();
StateHasChanged();

View File

@@ -6,19 +6,20 @@
@inject IStringLocalizer<Index> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@inject ISettingService SettingService
@inject ITimeZoneService TimeZoneService
@if (PageState.Site.AllowRegistration)
@if (_initialized)
{
if (!_userCreated)
@if (PageState.Site.AllowRegistration)
{
<AuthorizeView Roles="@RoleNames.Registered">
<Authorizing>
<text>...</text>
</Authorizing>
<Authorized>
if (!_userCreated)
{
if (PageState.User != null)
{
<ModuleMessage Message="@Localizer["Info.Registration.Exists"]" Type="MessageType.Info" />
</Authorized>
<NotAuthorized>
}
else
{
<ModuleMessage Message="@_passwordrequirements" Type="MessageType.Info" />
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
@@ -58,26 +59,42 @@
<input id="displayname" class="form-control" @bind="@_displayname" maxlength="50" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="timezone" HelpText="Your time zone" ResourceKey="TimeZone">Time Zone:</Label>
<div class="col-sm-9">
<select id="timezone" class="form-select" @bind="@_timezoneid">
<option value="">&lt;@SharedLocalizer["Not Specified"]&gt;</option>
@foreach (var timezone in _timezones)
{
<option value="@timezone.Id">@timezone.DisplayName</option>
}
</select>
</div>
</div>
</div>
<br />
<button type="button" class="btn btn-primary" @onclick="Register">@Localizer["Register"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
@if (_allowsitelogin)
{
<br /><br />
<br />
<br />
<NavLink href="@NavigateUrl("login")">@Localizer["Login"]</NavLink>
}
</form>
</NotAuthorized>
</AuthorizeView>
}
}
else
{
<ModuleMessage Message="@Localizer["Info.Registration.Disabled"]" Type="MessageType.Info" />
}
}
}
else
{
<ModuleMessage Message="@Localizer["Info.Registration.Disabled"]" Type="MessageType.Info" />
}
}
@code {
private bool _initialized = false;
private List<Models.TimeZone> _timezones;
private string _passwordrequirements;
private string _username = string.Empty;
private ElementReference form;
@@ -88,6 +105,7 @@ else
private string _confirm = string.Empty;
private string _email = string.Empty;
private string _displayname = string.Empty;
private string _timezoneid = string.Empty;
private bool _userCreated = false;
private bool _allowsitelogin = true;
@@ -97,6 +115,9 @@ else
{
_passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId);
_allowsitelogin = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:AllowSiteLogin", "true"));
_timezones = TimeZoneService.GetTimeZones();
_timezoneid = PageState.Site.TimeZoneId;
_initialized = true;
}
protected override void OnParametersSet()
@@ -125,6 +146,7 @@ else
Password = _password,
Email = _email,
DisplayName = (_displayname == string.Empty ? _username : _displayname),
TimeZoneId = _timezoneid,
PhotoFileId = null
};
user = await UserService.AddUserAsync(user);

View File

@@ -58,7 +58,7 @@ else
<td>@context.EffectiveDate</td>
<td>@context.ExpiryDate</td>
<td>
<ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || context.User.Username == UserNames.Host || context.User.UserId == PageState.User.UserId)" ResourceKey="DeleteUserRole" />
<ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.User.Username == UserNames.Host || context.User.UserId == PageState.User.UserId)" ResourceKey="DeleteUserRole" />
</td>
</Row>
</Pager>
@@ -180,27 +180,28 @@ else
private async Task DeleteUserRole(int UserRoleId)
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
try
{
try
var userrole = await UserRoleService.GetUserRoleAsync(UserRoleId);
if (userrole.Role.Name == RoleNames.Registered)
{
userrole.ExpiryDate = DateTime.UtcNow;
await UserRoleService.UpdateUserRoleAsync(userrole);
await logger.LogInformation("User {Username} Expired From Role {Role}", userrole.User.Username, userrole.Role.Name);
}
else
{
await UserRoleService.DeleteUserRoleAsync(UserRoleId);
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId);
AddModuleMessage(Localizer["Confirm.User.RoleRemoved"], MessageType.Success);
await GetUserRoles();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Removing User From Role {UserRoleId} {Error}", UserRoleId, ex.Message);
AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error);
await logger.LogInformation("User {Username} Removed From Role {Role}", userrole.User.Username, userrole.Role.Name);
}
AddModuleMessage(Localizer["Confirm.User.RoleRemoved"], MessageType.Success);
await GetUserRoles();
StateHasChanged();
}
else
catch (Exception ex)
{
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
await logger.LogError(ex, "Error Removing User From Role {UserRoleId} {Error}", UserRoleId, ex.Message);
AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error);
}
}
}

View File

@@ -0,0 +1,119 @@
@namespace Oqtane.Modules.Admin.Search
@inherits ModuleBase
@inject ISettingService SettingService
@inject IStringLocalizer<Index> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="searchprovider" HelpText="Specify the search provider for this site" ResourceKey="SearchProvider">Search Provider: </Label>
<div class="col-sm-9">
<input id="searchprovider" class="form-control" @bind="@_searchProvider" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="enabled" HelpText="Specify if search indexing is enabled" ResourceKey="Enabled">Indexing Enabled? </Label>
<div class="col-sm-9">
<select id="enabled" class="form-select" @bind="@_enabled">
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="lastindexedon" HelpText="The date/time which the site was last indexed on" ResourceKey="LastIndexedOn">Last Indexed: </Label>
<div class="col-sm-9">
<input id="lastindexedon" class="form-control" @bind="@_lastIndexedOn" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="ignorepages" HelpText="Comma delimited list of pages which should be ignored (based on their path)" ResourceKey="IgnorePages">Ignore Pages: </Label>
<div class="col-sm-9">
<textarea id="ignorepages" class="form-control" @bind="@_ignorePages" rows="3"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="ignoreentities" HelpText="Comma delimited list of entities which should be ignored" ResourceKey="IgnoreEntities">Ignore Entities: </Label>
<div class="col-sm-9">
<textarea id="ignoreentities" class="form-control" @bind="@_ignoreEntities" rows="3"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="minimumwordlength" HelpText="Minimum length of a word to be indexed" ResourceKey="MinimumWordLength">Word Length: </Label>
<div class="col-sm-9">
<input id="minimumwordlength" class="form-control" type="number" min="0" step="1" @bind="@_minimumWordLength" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="ignorewords" HelpText="Comma delimited list of words which should be ignored" ResourceKey="IgnoreWords">Ignore Words: </Label>
<div class="col-sm-9">
<textarea id="ignorewords" class="form-control" @bind="@_ignoreWords" rows="3"></textarea>
</div>
</div>
</div>
<br /><br />
<button type="button" class="btn btn-success" @onclick="Save">@SharedLocalizer["Save"]</button>
<ActionDialog Header="Reindex" Message="Are You Sure You Wish To Reindex Search Content?" Action="Reindex" Class="btn btn-danger" OnClick="@(async () => await Reindex())" ResourceKey="Reindex" />
<br /><br />
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
private string _searchProvider;
private string _enabled = "True";
private string _lastIndexedOn = "";
private string _ignorePages = "";
private string _ignoreEntities = "File";
private string _minimumWordLength = "3";
private string _ignoreWords = "the,be,to,of,and,a,i,in,that,have,it,for,not,on,with,he,as,you,do,at,this,but,his,by,from,they,we,say,her,she,or,an,will,my,one,all,would,there,their,what,so,up,out,if,about,who,get,which,go,me,when,make,can,like,time,no,just,him,know,take,people,into,year,your,good,some,could,them,see,other,than,then,now,look,only,come,its,over,think,also,back,after,use,two,how,our,work,first,well,way,even,new,want,because,any,these,give,day,most,us";
protected override async Task OnInitializedAsync()
{
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
_searchProvider = SettingService.GetSetting(settings, "Search_SearchProvider", Constants.DefaultSearchProviderName);
_enabled = SettingService.GetSetting(settings, "Search_Enabled", _enabled);
_lastIndexedOn = SettingService.GetSetting(settings, "Search_LastIndexedOn", _lastIndexedOn);
_ignorePages = SettingService.GetSetting(settings, "Search_IgnorePages", _ignorePages);
_ignoreEntities = SettingService.GetSetting(settings, "Search_IgnoreEntities", _ignoreEntities);
_minimumWordLength = SettingService.GetSetting(settings, "Search_MininumWordLength", _minimumWordLength);
_ignoreWords = SettingService.GetSetting(settings, "Search_IgnoreWords", _ignoreWords);
}
private async Task Save()
{
try
{
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
settings = SettingService.SetSetting(settings, "Search_SearchProvider", _searchProvider);
settings = SettingService.SetSetting(settings, "Search_Enabled", _enabled);
settings = SettingService.SetSetting(settings, "Search_LastIndexedOn", _lastIndexedOn, true);
settings = SettingService.SetSetting(settings, "Search_IgnorePages", _ignorePages, true);
settings = SettingService.SetSetting(settings, "Search_IgnoreEntities", _ignoreEntities, true);
settings = SettingService.SetSetting(settings, "Search_MininumWordLength", _minimumWordLength, true);
settings = SettingService.SetSetting(settings, "Search_IgnoreWords", _ignoreWords, true);
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
AddModuleMessage(Localizer["Success.Save"], MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Search Settings {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Save"], MessageType.Error);
}
}
private async Task Reindex()
{
try
{
_lastIndexedOn = DateTime.MinValue.ToString();
await Save();
AddModuleMessage(Localizer["Message.Reindex"], MessageType.Success);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Search Settings {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Save"], MessageType.Error);
}
}
}

View File

@@ -0,0 +1,153 @@
@using Oqtane.Services
@using System.Net
@namespace Oqtane.Modules.Admin.SearchResults
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject ISearchResultsService SearchResultsService
@inject ISettingService SettingService
@inject IStringLocalizer<Index> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
@attribute [StreamRendering] // attribute allows the progress indicator to be displayed
<div class="search-result-container">
<div class="row">
<div class="col">
<form method="post" @formname="SearchResultsForm" @onsubmit="Search" data-enhance>
<div class="input-group mb-3">
<span class="input-group-text">@Localizer["SearchLabel"]</span>
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<input type="text" name="keywords" class="form-control shadow-none" maxlength="50"
aria-label="Keywords"
placeholder="@Localizer["SearchPlaceholder"]"
@bind="@_keywords">
<button class="btn btn-primary" type="submit">@SharedLocalizer["Search"]</button>
<a class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Reset"]</a>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col-md-12 mb-3">
@if (_loading)
{
<div class="app-progress-indicator"></div>
}
else
{
@if (_searchResults != null && _searchResults.Results != null)
{
if (_searchResults.Results.Any())
{
<Pager Items="@_searchResults?.Results"
Format="Grid"
PageSize="@_pageSize"
DisplayPages="@_displayPages"
CurrentPage="@_currentPage"
Columns="1"
Toolbar="Bottom"
Parameters="@($"q={_keywords}")">
<Row>
<div class="search-item mb-2">
<h4 class="mb-1"><a href="@context.Url">@context.Title</a></h4>
<p class="mb-0 text-body-secondary">@((MarkupString)context.Snippet)</p>
</div>
</Row>
</Pager>
}
else
{
<div class="alert alert-info show mt-3" role="alert">
@Localizer["NoResult"]
</div>
}
}
<div class="clearfix"></div>
}
</div>
</div>
</div>
@code {
public override string RenderMode => RenderModes.Static;
private const string SearchDefaultPageSize = "10";
private string _includeEntities;
private string _excludeEntities;
private string _fromDate;
private string _toDate;
private string _pageSize;
private string _sortField;
private string _sortOrder;
private string _bodyLength;
private string _currentPage = "0";
private string _displayPages = "7";
private string _keywords;
private SearchResults _searchResults;
private bool _loading;
[SupplyParameterFromForm(FormName = "SearchResultsForm")]
public string KeyWords { get => ""; set => _keywords = value; }
protected override async Task OnInitializedAsync()
{
_includeEntities = SettingService.GetSetting(ModuleState.Settings, "SearchResults_IncludeEntities", "");
_excludeEntities = SettingService.GetSetting(ModuleState.Settings, "SearchResults_ExcludeEntities", "");
_fromDate = SettingService.GetSetting(ModuleState.Settings, "SearchResults_FromDate", DateTime.MinValue.ToString());
_toDate = SettingService.GetSetting(ModuleState.Settings, "SearchResults_ToDate", DateTime.MaxValue.ToString());
_pageSize = SettingService.GetSetting(ModuleState.Settings, "SearchResults_PageSize", SearchDefaultPageSize);
_sortField = SettingService.GetSetting(ModuleState.Settings, "SearchResults_SortField", "Relevance");
_sortOrder = SettingService.GetSetting(ModuleState.Settings, "SearchResults_SortOrder", "Descending");
_bodyLength = SettingService.GetSetting(ModuleState.Settings, "SearchResults_BodyLength", "255");
if (PageState.QueryString.ContainsKey("p"))
{
_currentPage = PageState.QueryString["p"];
}
if (_keywords == null && PageState.QueryString.ContainsKey("q"))
{
_keywords = WebUtility.UrlDecode(PageState.QueryString["q"]);
await PerformSearch();
}
}
private void Search()
{
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, $"page=1&q={WebUtility.UrlEncode(_keywords)}"));
}
private async Task PerformSearch()
{
_loading = true;
StateHasChanged();
if (!string.IsNullOrEmpty(_keywords))
{
var searchQuery = new SearchQuery
{
SiteId = PageState.Site.SiteId,
Alias = PageState.Alias,
Keywords = _keywords,
IncludeEntities = _includeEntities,
ExcludeEntities = _excludeEntities,
FromDate = (!string.IsNullOrEmpty(_fromDate)) ? DateTime.Parse(_fromDate) : DateTime.MinValue,
ToDate = (!string.IsNullOrEmpty(_toDate)) ? DateTime.Parse(_toDate) : DateTime.MaxValue,
PageSize = int.MaxValue,
PageIndex = 0,
SortField = (!string.IsNullOrEmpty(_sortField)) ? (SearchSortField)Enum.Parse(typeof(SearchSortField), _sortField) : SearchSortField.Relevance,
SortOrder = (!string.IsNullOrEmpty(_sortOrder)) ? (SearchSortOrder)Enum.Parse(typeof(SearchSortOrder), _sortOrder) : SearchSortOrder.Descending,
BodyLength = (!string.IsNullOrEmpty(_bodyLength)) ? int.Parse(_bodyLength) : 255
};
_searchResults = await SearchResultsService.GetSearchResultsAsync(searchQuery);
}
else
{
AddModuleMessage(Localizer["NoCriteria"], MessageType.Info, "bottom");
}
_loading = false;
StateHasChanged();
}
}

View File

@@ -0,0 +1,19 @@
using Oqtane.Documentation;
using Oqtane.Models;
using Oqtane.Shared;
namespace Oqtane.Modules.Admin.SearchResults
{
[PrivateApi("Mark this as private, since it's not very useful in the public docs")]
public class ModuleInfo : IModule
{
public ModuleDefinition ModuleDefinition => new ModuleDefinition
{
Name = "Search Results",
Description = "Search Results",
Categories = "Admin",
Version = Constants.Version,
SettingsType = "Oqtane.Modules.Admin.SearchResults.Settings, Oqtane.Client"
};
}
}

View File

@@ -0,0 +1,123 @@
@namespace Oqtane.Modules.Admin.SearchResults
@inherits ModuleBase
@inject ISettingService SettingService
@implements Oqtane.Interfaces.ISettingsControl
@inject IStringLocalizer<Settings> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="includeentities" ResourceKey="IncludeEntities" ResourceType="@resourceType" HelpText="Comma delimited list of entities to include in the search results. By default all entities will be included.">Include Entities: </Label>
<div class="col-sm-9">
<input id="includeentities" type="text" class="form-control" @bind="@_includeEntities" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="excludeentities" ResourceKey="ExcludeEntities" ResourceType="@resourceType" HelpText="Comma delimited list of entities to exclude from search results. By default no entities will be excluded.">Exclude Entities: </Label>
<div class="col-sm-9">
<input id="excludeentities" class="form-control" @bind="@_excludeEntities" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="daterange" ResourceKey="DateRange" ResourceType="@resourceType" HelpText="Enter the date range for search results. The default includes all content.">Date Range: </Label>
<div class="col-sm-9">
<div class="input-group">
<input type="date" class="form-control" @bind="@_fromDate" />
<span class="input-group-text">@Localizer["To"]</span>
<input type="date" class="form-control" @bind="@_toDate" />
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="pagesize" ResourceKey="PageSize" ResourceType="@resourceType" HelpText="The maximum number of search results to retrieve. The default is unlimited.">Page Size: </Label>
<div class="col-sm-9">
<input id="pagesize" type="text" class="form-control" @bind="@_pageSize" />
</div>
</div>
<hr />
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="sortfield" ResourceKey="SortField" ResourceType="@resourceType" HelpText="Specify the default sort field">Sort By: </Label>
<div class="col-sm-9">
<select id="softfield" class="form-select" @bind="@_sortField">
<option value="Relevance">@Localizer["Relevance"]</option>
<option value="Title">@Localizer["Title"]</option>
<option value="LastModified">@Localizer["LastModified"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="sortorder" ResourceKey="SortOrder" ResourceType="@resourceType" HelpText="Specify the default sort order">Sort Order: </Label>
<div class="col-sm-9">
<select id="softorder" class="form-select" @bind="@_sortOrder">
<option value="Ascending">@Localizer["Ascending"]</option>
<option value="Descending">@Localizer["Descending"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="bodylength" ResourceKey="BodyLength" ResourceType="@resourceType" HelpText="The number of characters displayed for each search result summary. The default is 255 characters.">Body Size: </Label>
<div class="col-sm-9">
<input id="bodylength" type="text" class="form-control" @bind="@_bodyLength" />
</div>
</div>
</div>
</form>
@code {
private string resourceType = "Oqtane.Modules.Admin.SearchResults.Settings, Oqtane.Client"; // for localization
private ElementReference form;
private bool validated = false;
private string _includeEntities;
private string _excludeEntities;
private DateTime? _fromDate = null;
private DateTime? _toDate = null;
private string _pageSize;
private string _sortField;
private string _sortOrder;
private string _bodyLength;
protected override void OnInitialized()
{
try
{
_includeEntities = SettingService.GetSetting(ModuleState.Settings, "SearchResults_IncludeEntities", "");
_excludeEntities = SettingService.GetSetting(ModuleState.Settings, "SearchResults_ExcludeEntities", "");
var fromDate = SettingService.GetSetting(ModuleState.Settings, "SearchResults_FromDate", "");
_fromDate = (string.IsNullOrEmpty(fromDate)) ? null : DateTime.Parse(fromDate);
var toDate = SettingService.GetSetting(ModuleState.Settings, "SearchResults_ToDate", "");
_toDate = (string.IsNullOrEmpty(toDate)) ? null : DateTime.Parse(toDate);
_pageSize = SettingService.GetSetting(ModuleState.Settings, "SearchResults_PageSize", "");
_sortField = SettingService.GetSetting(ModuleState.Settings, "SearchResults_SortField", "Relevance");
_sortOrder = SettingService.GetSetting(ModuleState.Settings, "SearchResults_SortOrder", "Descending");
_bodyLength = SettingService.GetSetting(ModuleState.Settings, "SearchResults_BodyLength", "255");
}
catch (Exception ex)
{
AddModuleMessage(ex.Message, MessageType.Error);
}
}
public async Task UpdateSettings()
{
try
{
var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
settings = SettingService.SetSetting(settings, "SearchResults_IncludeEntities", _includeEntities);
settings = SettingService.SetSetting(settings, "SearchResults_ExcludeEntities", _excludeEntities);
settings = SettingService.SetSetting(settings, "SearchResults_From", _fromDate.ToString());
settings = SettingService.SetSetting(settings, "SearchResults_To", _toDate.ToString());
settings = SettingService.SetSetting(settings, "SearchResults_PageSize", _pageSize);
settings = SettingService.SetSetting(settings, "SearchResults_SortField", _sortField);
settings = SettingService.SetSetting(settings, "SearchResults_SortOrder", _sortOrder);
settings = SettingService.SetSetting(settings, "SearchResults_BodyLength", _bodyLength);
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
}
catch (Exception ex)
{
AddModuleMessage(ex.Message, MessageType.Error);
}
}
}

View File

@@ -0,0 +1,226 @@
@namespace Oqtane.Modules.Admin.Settings
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject ISettingService SettingService
@inject IStringLocalizer<Edit> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="entityName" HelpText="Entity Name" ResourceKey="EntityName">Entity:</Label>
<div class="col-sm-9">
<div class="input-group">
@if (_entityNameElement == "input")
{
<input id="entityName" class="form-control" @bind="@_entityName" maxlength="256" required />
}
else
{
<select class="form-select custom-select" value="@_entityName" @onchange="(e => EntityNameChanged(e))">
<option value="-">&lt;@Localizer["Select Entity"]&gt;</option>
@foreach (var entityName in _entityNames)
{
<option value="@entityName">@entityName</option>
}
</select>
}
<button type="button" class="btn btn-secondary" @onclick="@EntityNameClicked" tabindex="-1">@_entityNameTitle</button>
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="entityId" HelpText="Entity Id" ResourceKey="EntityId">Id:</Label>
<div class="col-sm-9">
<div class="input-group">
@if (_entityIdElement == "input")
{
<input id="entityId" class="form-control" @bind="@_entityId" maxlength="256" required />
}
else
{
<select class="form-select custom-select" @bind="@_entityId">
<option value="-">&lt;@Localizer["Select Id"]&gt;</option>
@foreach (var entityId in _entityIds)
{
<option value="@entityId">@entityId</option>
}
</select>
}
<button type="button" class="btn btn-secondary" @onclick="@EntityIdClicked" tabindex="-1">@_entityIdTitle</button>
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="settingName" HelpText="Setting Name" ResourceKey="SettingName">Name:</Label>
<div class="col-sm-9">
<input id="settingName" class="form-control" @bind="@_settingName" maxlength="256" required />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="settingValue" HelpText="Setting Value" ResourceKey="SettingValue">Value:</Label>
<div class="col-sm-9">
<input id="SettingValue" class="form-control" @bind="@_settingValue" maxlength="256" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="isPrivate" HelpText="Private" ResourceKey="IsPrivate">Private?</Label>
<div class="col-sm-9">
<select id="isPrivate" class="form-select" @bind="@_isPrivate">
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<br /><br />
<button type="button" class="btn btn-success" @onclick="SaveSetting">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
</div>
</form>
@code {
private ElementReference form;
private bool validated = false;
private string _entityName = "-";
private List<string> _entityNames = new List<string>();
private string _entityNameElement = "select";
private string _entityNameTitle = "";
private string _entityId = "-";
private List<int> _entityIds = new List<int>();
private string _entityIdElement = "select";
private string _entityIdTitle = "";
private string _settingName = "";
private string _settingValue = "";
private string _isPrivate = "True";
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnInitializedAsync()
{
try
{
_entityNameTitle = Localizer["Input"];
_entityIdTitle = Localizer["Input"];
// default entity names
_entityNames.Add(EntityNames.Host);
_entityNames.Add(EntityNames.Job);
_entityNames.Add(EntityNames.ModuleDefinition);
_entityNames.Add(EntityNames.Theme);
_entityNames.Add(EntityNames.Tenant);
_entityNames.Add(EntityNames.Site);
_entityNames.Add(EntityNames.Role);
_entityNames.Add(EntityNames.Page);
_entityNames.Add(EntityNames.Module);
_entityNames.Add(EntityNames.Folder);
_entityNames.Add(EntityNames.User);
_entityNames.Add(EntityNames.Visitor);
// custom entity names
var entityNames = await SettingService.GetEntityNamesAsync();
foreach (var entityName in entityNames)
{
if (!_entityNames.Contains(entityName))
{
_entityNames.Add(entityName);
}
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Setting {Error}", ex.Message);
AddModuleMessage(Localizer["Error.LoadSetting"], MessageType.Error);
}
}
private void EntityNameClicked()
{
if (_entityNameElement == "select")
{
_entityName = "";
_entityNameElement = "input";
_entityNameTitle = Localizer["Select"];
_entityId = "";
_entityIdElement = "input";
_entityIdTitle = Localizer["Select"];
}
else
{
_entityName = "-";
_entityNameElement = "select";
_entityNameTitle = Localizer["Input"];
}
}
private void EntityIdClicked()
{
if (_entityIdElement == "select")
{
_entityId = "";
_entityIdElement = "input";
_entityIdTitle = Localizer["Select"];
}
else
{
_entityId = "-";
_entityIdElement = "select";
_entityIdTitle = Localizer["Input"];
}
}
private async void EntityNameChanged(ChangeEventArgs e)
{
try
{
_entityName = e.Value.ToString();
_entityId = "-";
_entityIdElement = "select";
_entityIdTitle = Localizer["Input"];
if (_entityName != "-")
{
_entityIds = await SettingService.GetEntityIdsAsync(_entityName);
}
else
{
_entityIds = new List<int>();
}
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On EntityNameChanged");
}
}
private async Task SaveSetting()
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form) && _entityName != "-" && int.TryParse(_entityId, out int entityId))
{
var setting = new Setting();
setting.EntityName = _entityName;
setting.EntityId = entityId;
setting.SettingName = _settingName;
setting.SettingValue = _settingValue;
setting.IsPrivate = (bool.Parse(_isPrivate));
try
{
setting = await SettingService.AddSettingAsync(setting);
await logger.LogInformation("Setting Saved {Setting}", setting);
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Setting {Setting} {Error}", setting, ex.Message);
AddModuleMessage(Localizer["Error.SaveSetting"], MessageType.Error);
}
}
else
{
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
}
}
}

View File

@@ -0,0 +1,122 @@
@namespace Oqtane.Modules.Admin.Settings
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject ISettingService SettingService
@inject IStringLocalizer<Edit> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="entityName" HelpText="Entity Name" ResourceKey="EntityName">Entity:</Label>
<div class="col-sm-9">
<input id="entityName" class="form-control" @bind="@_entityName" maxlength="256" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="entityId" HelpText="Entity Id" ResourceKey="EntityId">Id:</Label>
<div class="col-sm-9">
<input id="entityId" class="form-control" @bind="@_entityId" maxlength="256" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="settingName" HelpText="Setting Name" ResourceKey="SettingName">Name:</Label>
<div class="col-sm-9">
<input id="settingName" class="form-control" @bind="@_settingName" maxlength="256" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="settingValue" HelpText="Setting Value" ResourceKey="SettingValue">Value:</Label>
<div class="col-sm-9">
<input id="SettingValue" class="form-control" @bind="@_settingValue" maxlength="256" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="isPrivate" HelpText="Private" ResourceKey="IsPrivate">Private?</Label>
<div class="col-sm-9">
<select id="isPrivate" class="form-select" @bind="@_isPrivate">
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<br /><br />
<button type="button" class="btn btn-success" @onclick="SaveSetting">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
<br /><br />
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
</div>
</form>
@code {
private ElementReference form;
private bool validated = false;
private int _settingId;
private string _entityName;
private string _entityId;
private string _settingName;
private string _settingValue;
private string _isPrivate;
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnInitializedAsync()
{
_settingId = int.Parse(PageState.QueryString["id"]);
_entityName = PageState.QueryString["entity"];
try
{
var setting = await SettingService.GetSettingAsync(_entityName, _settingId);
if (setting != null)
{
_entityId = setting.EntityId.ToString();
_settingName = setting.SettingName;
_settingValue = setting.SettingValue;
_isPrivate = setting.IsPrivate.ToString();
_createdby = setting.CreatedBy;
_createdon = setting.CreatedOn;
_modifiedby = setting.ModifiedBy;
_modifiedon = setting.ModifiedOn;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Setting {SettingId} {Error}", _settingId, ex.Message);
AddModuleMessage(Localizer["Error.LoadSetting"], MessageType.Error);
}
}
private async Task SaveSetting()
{
validated = true;
var interop = new Interop(JSRuntime);
if (await interop.FormValid(form))
{
var setting = await SettingService.GetSettingAsync(_entityName, _settingId);
setting.SettingValue = _settingValue;
setting.IsPrivate = (_isPrivate != null && Boolean.Parse(_isPrivate));
try
{
setting = await SettingService.UpdateSettingAsync(setting);
await logger.LogInformation("Setting Saved {Setting}", setting);
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Setting {Setting} {Error}", setting, ex.Message);
AddModuleMessage(Localizer["Error.SaveSetting"], MessageType.Error);
}
}
else
{
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
}
}
}

View File

@@ -0,0 +1,56 @@
@namespace Oqtane.Modules.Admin.Settings
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject ISettingService SettingService
@inject IStringLocalizer<ImportSettings> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="settings" HelpText="Provide settings in comma delimited format using the column template specified" ResourceKey="Settings">Settings:</Label>
<div class="col-sm-9">
<textarea id="settings" class="form-control" @bind="@_settings" rows="5" required></textarea>
</div>
</div>
</div>
<br />
<button type="button" class="btn btn-success" @onclick="Import">@Localizer["Import"]</button>&nbsp;
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
@code {
private string _settings = "Entity,Id,Name,Value,Private\n";
public override string Title => "Import Settings";
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
private async Task Import()
{
try
{
if (!string.IsNullOrEmpty(_settings))
{
ShowProgressIndicator();
var result = await SettingService.ImportSettingsAsync(new Result { Message = _settings });
if (result.Success)
{
AddModuleMessage(Localizer["Message.Import.Success"], MessageType.Success);
}
else
{
AddModuleMessage(Localizer["Message.Import.Failure"], MessageType.Error);
}
HideProgressIndicator();
}
else
{
AddModuleMessage(Localizer["Message.Import.Validation"], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Importing Settings {Error}", ex.Message);
AddModuleMessage(Localizer["Error.Import"], MessageType.Error);
}
}
}

View File

@@ -0,0 +1,146 @@
@namespace Oqtane.Modules.Admin.Settings
@inherits ModuleBase
@inject ISettingService SettingService
@inject IStringLocalizer<Index> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<div class="container">
<div class="row mb-1 align-items-center">
<div class="col-sm-4">
<ActionLink Action="Add" Text="Add Setting" Security="SecurityAccessLevel.Host" ResourceKey="AddSetting" ReturnUrl="@(NavigateUrl(PageState.Page.Path, AddUrlParameters(_entityName, _entityId)))" />
<ActionLink Action="ImportSettings" Text="Import" Class="btn btn-secondary ms-1" Security="SecurityAccessLevel.Host" ResourceKey="ImportSettings" ReturnUrl="@(NavigateUrl(PageState.Page.Path, AddUrlParameters(_entityName, _entityId)))" />
</div>
<div class="col-sm-4">
<select class="form-select custom-select" value="@_entityName" @onchange="(e => EntityNameChanged(e))">
<option value="-">&lt;@Localizer["Select Entity"]&gt;</option>
@foreach (var entityName in _entityNames)
{
<option value="@entityName">@entityName</option>
}
</select>
</div>
<div class="col-sm-4">
<select class="form-select custom-select" value="@_entityId" @onchange="(e => EntityIdChanged(e))">
<option value="-">&lt;@Localizer["Select Id"]&gt;</option>
@foreach (var entityId in _entityIds)
{
<option value="@entityId">@entityId</option>
}
</select>
</div>
</div>
</div>
<br />
<Pager Items="@_settings" SearchProperties="SettingName,SettingValue">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@Localizer["Name"]</th>
<th>@Localizer["Value"]</th>
</Header>
<Row>
<td><ActionLink Action="Edit" Text="Edit" Parameters="@($"entity={context.EntityName}&id={context.SettingId}")" Security="SecurityAccessLevel.Host" ResourceKey="EditSetting" ReturnUrl="@(NavigateUrl(PageState.Page.Path, AddUrlParameters(_entityName, _entityId)))" /></td>
<td><ActionDialog Header="Delete Setting" Message="@string.Format(Localizer["Confirm.DeleteSetting"], context.SettingName)" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteSetting(context))" ResourceKey="DeleteSetting" /></td>
<td>@context.SettingName</td>
<td>@context.SettingValue</td>
</Row>
</Pager>
@code {
private string _entityName = "-";
private List<string> _entityNames = new List<string>();
private string _entityId = "-";
private List<int> _entityIds = new List<int>();
private List<Setting> _settings = new List<Setting>();
public override string UrlParametersTemplate => "/{entityname}/{entityid}";
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnParametersSetAsync()
{
_entityNames = await SettingService.GetEntityNamesAsync();
if (UrlParameters.ContainsKey("entityname"))
{
_entityName = UrlParameters["entityname"];
await GetEntityIds();
}
if (UrlParameters.ContainsKey("entityid"))
{
_entityId = UrlParameters["entityid"];
await GetSettings();
}
}
private async Task GetEntityIds()
{
if (_entityName != "-")
{
_entityIds = await SettingService.GetEntityIdsAsync(_entityName);
}
else
{
_entityIds = new List<int>();
}
}
private async Task GetSettings()
{
if (_entityName != "-" && _entityId != "-")
{
_settings = await SettingService.GetSettingsAsync(_entityName, int.Parse(_entityId), "");
_settings = _settings.OrderBy(item => item.SettingName).ToList();
}
else
{
_settings = new List<Setting>();
}
}
private async void EntityNameChanged(ChangeEventArgs e)
{
try
{
_entityName = e.Value.ToString();
_entityId = "-";
await GetEntityIds();
await GetSettings();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On EntityNameChanged");
}
}
private async void EntityIdChanged(ChangeEventArgs e)
{
try
{
_entityId = e.Value.ToString();
await GetSettings();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On EntityIdChanged");
}
}
private async Task DeleteSetting(Setting setting)
{
try
{
await SettingService.DeleteSettingAsync(setting.EntityName, setting.EntityId, setting.SettingName);
await logger.LogInformation("Setting Deleted {Setting}", setting);
await GetSettings();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Setting {Setting} {Error}", setting, ex.Message);
AddModuleMessage(Localizer["Error.DeleteSetting"], MessageType.Error);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -109,7 +109,7 @@ else
<hr class="app-rule" />
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter the name for the database" ResourceKey="TenantName">Name: </Label>
<Label Class="col-sm-3" For="name" HelpText="Enter the name for the database. Note that this will be the tenant name which is used within the framework to identify the database." ResourceKey="TenantName">Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_tenantName" maxlength="100" required />
</div>
@@ -118,42 +118,42 @@ else
<Label Class="col-sm-3" For="databaseType" HelpText="Select the database type" ResourceKey="DatabaseType">Type: </Label>
<div class="col-sm-9">
@if (_databases != null)
{
<div class="input-group">
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
@foreach (var database in _databases)
{
<option value="@database.Name">@Localizer[@database.Name]</option>
}
</select>
@if (!_showConnectionString)
{
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionString"]</button>
}
else
{
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionParameters"]</button>
}
</div>
}
</div>
{
<div class="input-group">
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
@foreach (var database in _databases)
{
<option value="@database.Name">@Localizer[@database.Name]</option>
}
</select>
@if (!_showConnectionString)
{
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionString"]</button>
}
else
{
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionParameters"]</button>
}
</div>
}
</div>
</div>
@if (!_showConnectionString)
{
if (_databaseConfigType != null)
{
@DatabaseConfigComponent
}
}
else
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="connectionstring" HelpText="Enter a complete connection string including all parameters and delimiters" ResourceKey="ConnectionString">Settings:</Label>
<div class="col-sm-9">
<textarea id="connectionstring" class="form-control" @bind="@_connectionString" rows="3"></textarea>
</div>
</div>
}
@if (!_showConnectionString)
{
if (_databaseConfigType != null)
{
@DatabaseConfigComponent
}
}
else
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="connectionstring" HelpText="Enter a complete connection string including all parameters and delimiters" ResourceKey="ConnectionString">Settings:</Label>
<div class="col-sm-9">
<textarea id="connectionstring" class="form-control" @bind="@_connectionString" rows="3"></textarea>
</div>
</div>
}
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="hostUsername" HelpText="Enter the username of an existing host user" ResourceKey="HostUsername">Host Username:</Label>
<div class="col-sm-9">
@@ -216,7 +216,7 @@ else
_tenantid = _tenants.First(item => item.Name == TenantNames.Master).TenantId.ToString();
}
_urls = PageState.Alias.Name;
_themeList = await ThemeService.GetThemesAsync();
_themeList = await ThemeService.GetThemesAsync(PageState.Site.SiteId);
_themes = ThemeService.GetThemeControls(_themeList);
if (_themes.Any(item => item.TypeName == Constants.DefaultTheme))
{
@@ -237,7 +237,7 @@ else
}
else
{
_databaseName = "LocalDB";
_databaseName = Constants.DefaultDBName;
}
LoadDatabaseConfigComponent();
}
@@ -390,6 +390,8 @@ else
config.DatabaseType = tenant.DBType;
config.ConnectionString = tenant.DBConnectionString;
config.IsNewTenant = false;
config.HostEmail = PageState.User.Email;
config.HostName = PageState.User.DisplayName;
}
}
@@ -403,6 +405,7 @@ else
config.SiteTemplate = _sitetemplatetype;
config.RenderMode = _rendermode;
config.Runtime = _runtime;
config.Register = false;
ShowProgressIndicator();

View File

@@ -83,24 +83,15 @@ else
{
@if (_connection != "-")
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="databasetype" HelpText="The database type" ResourceKey="DatabaseType">Type: </Label>
<div class="col-sm-9">
@if (_databases != null)
{
<select id="databasetype" class="form-select" @bind="@_databasetype" required>
<option value="-">&lt;@Localizer["Type.Select"]&gt;</option>
@foreach (var database in _databases)
{
<option value="@database.Name">@Localizer[@database.Name]</option>
}
</select>
}
</div>
</div>
@if (!string.IsNullOrEmpty(_tenant))
{
<div class="row mb-1 align-items-center">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="databasetype" HelpText="The database type" ResourceKey="DatabaseType">Type: </Label>
<div class="col-sm-9">
<input id="databasetype" class="form-control" @bind="@_databasetype" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="tenant" HelpText="The database using this connection" ResourceKey="Tenant">Database: </Label>
<div class="col-sm-9">
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
@@ -204,12 +195,13 @@ else
{
_connectionstring = _connections[_connection].ToString();
_tenant = "";
_databasetype = "-";
_databasetype = "";
var tenant = _tenants.FirstOrDefault(item => item.DBConnectionString == _connection);
if (tenant != null)
{
_tenant = tenant.Name;
_databasetype = _databases.FirstOrDefault(item => item.DBType == tenant.DBType).Name;
// hack - there are 3 providers with SqlServerDatabase DBTypes - so we are choosing the last one in alphabetical order
_databasetype = _databases.Where(item => item.DBType == tenant.DBType).OrderBy(item => item.Name).Last()?.Name;
}
}
else
@@ -220,7 +212,7 @@ else
}
else
{
_databasetype = "LocalDB";
_databasetype = Constants.DefaultDBName;
}
_showConnectionString = false;
LoadDatabaseConfigComponent();

View File

@@ -2,223 +2,280 @@
@inherits ModuleBase
@inject ISystemService SystemService
@inject IInstallationService InstallationService
@inject IMigrationHistoryService MigrationHistoryService
@inject ITenantService TenantService
@inject IStringLocalizer<Index> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer
<TabStrip>
<TabPanel Name="Info" Heading="Info" ResourceKey="Info">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="version" HelpText="Framework Version" ResourceKey="FrameworkVersion">Framework Version: </Label>
<div class="col-sm-9">
<input id="version" class="form-control" @bind="@_version" readonly />
@if (_initialized)
{
<TabStrip>
<TabPanel Name="Info" Heading="Info" ResourceKey="Info">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="version" HelpText="Framework Version" ResourceKey="FrameworkVersion">Framework Version: </Label>
<div class="col-sm-9">
<input id="version" class="form-control" @bind="@_version" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="clrversion" HelpText="Common Language Runtime Version" ResourceKey="CLRVersion">CLR Version: </Label>
<div class="col-sm-9">
<input id="clrversion" class="form-control" @bind="@_clrversion" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="osversion" HelpText="Operating System Version" ResourceKey="OSVersion">OS Version: </Label>
<div class="col-sm-9">
<input id="osversion" class="form-control" @bind="@_osversion" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="process" HelpText="Indicates if the current process is 32 bit or 64 bit" ResourceKey="Process">Process: </Label>
<div class="col-sm-9">
<input id="process" class="form-control" @bind="@_process" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="machinename" HelpText="Machine Name" ResourceKey="MachineName">Machine Name: </Label>
<div class="col-sm-9">
<input id="machinename" class="form-control" @bind="@_machinename" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="ipaddress" HelpText="Server IP Address" ResourceKey="IPAddress">IP Address: </Label>
<div class="col-sm-9">
<input id="ipaddress" class="form-control" @bind="@_ipaddress" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="environment" HelpText="Environment name" ResourceKey="Environment">Environment: </Label>
<div class="col-sm-9">
<input id="environment" class="form-control" @bind="@_environment" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="contentrootpath" HelpText="Root Path" ResourceKey="ContentRootPath">Root Path: </Label>
<div class="col-sm-9">
<input id="contentrootpath" class="form-control" @bind="@_contentrootpath" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="webrootpath" HelpText="Web Path" ResourceKey="WebRootPath">Web Path: </Label>
<div class="col-sm-9">
<input id="webrootpath" class="form-control" @bind="@_webrootpath" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="servertime" HelpText="Server Date/Time (in UTC)" ResourceKey="ServerTime">Server Date/Time: </Label>
<div class="col-sm-9">
<input id="servertime" class="form-control" @bind="@_servertime" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="workingset" HelpText="Memory Allocation Of Service (in MB)" ResourceKey="WorkingSet">Memory Allocation: </Label>
<div class="col-sm-9">
<input id="workingset" class="form-control" @bind="@_workingset" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="installationid" HelpText="The Unique Identifier For Your Installation" ResourceKey="InstallationId">Installation ID: </Label>
<div class="col-sm-9">
<input id="installationid" class="form-control" @bind="@_installationid" readonly />
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="clrversion" HelpText="Common Language Runtime Version" ResourceKey="CLRVersion">CLR Version: </Label>
<div class="col-sm-9">
<input id="clrversion" class="form-control" @bind="@_clrversion" readonly />
<br /><br />
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
</TabPanel>
<TabPanel Name="Options" Heading="Options" ResourceKey="Options">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="detailederrors" HelpText="Specify If Detailed Errors Are Enabled For Blazor. This Option Should Not Not Be Enabled In Production." ResourceKey="DetailedErrors">Detailed Errors? </Label>
<div class="col-sm-9">
<select id="detailederrors" class="form-select" @bind="@_detailederrors">
<option value="true">@SharedLocalizer["True"]</option>
<option value="false">@SharedLocalizer["False"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="logginglevel" HelpText="The Minimum Logging Level For The Event Log. This Option Can Be Used To Control The Volume Of Items Stored In Your Event Log." ResourceKey="LoggingLevel">Logging Level: </Label>
<div class="col-sm-9">
<select id="logginglevel" class="form-select" @bind="@_logginglevel">
<option value="Trace">@Localizer["Trace"]</option>
<option value="Debug">@Localizer["Debug"]</option>
<option value="Information">@Localizer["Information"]</option>
<option value="Warning">@Localizer["Warning"]</option>
<option value="Error">@Localizer["Error"]</option>
<option value="Critical">@Localizer["Critical"]</option>
<option value="None">@Localizer["None"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="notificationlevel" HelpText="The Minimum Logging Level For Which Notifications Should Be Sent To Host Users." ResourceKey="NotificationLevel">Notification Level: </Label>
<div class="col-sm-9">
<select id="notificationlevel" class="form-select" @bind="@_notificationlevel">
<option value="Trace">@Localizer["Trace"]</option>
<option value="Debug">@Localizer["Debug"]</option>
<option value="Information">@Localizer["Information"]</option>
<option value="Warning">@Localizer["Warning"]</option>
<option value="Error">@Localizer["Error"]</option>
<option value="Critical">@Localizer["Critical"]</option>
<option value="None">@Localizer["None"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="swagger" HelpText="Specify If Swagger Is Enabled For Your Server API" ResourceKey="Swagger">Swagger Enabled? </Label>
<div class="col-sm-9">
<select id="swagger" class="form-select" @bind="@_swagger">
<option value="true">@SharedLocalizer["True"]</option>
<option value="false">@SharedLocalizer["False"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="cachecontrol" HelpText="Provide a Cache-Control directive for static assets. For example 'public, max-age=60' indicates that static assets should be cached for 60 seconds. A blank value indicates caching is not enabled." ResourceKey="CacheControl">Static Asset Caching: </Label>
<div class="col-sm-9">
<input id="cachecontrol" class="form-control" @bind="@_cachecontrol" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="packageregistryurl" HelpText="Specify The Url Of The Package Manager Service For Installing Modules, Themes, And Translations. If This Field Is Blank It Means The Package Manager Service Is Disabled For This Installation." ResourceKey="PackageManager">Package Manager Url: </Label>
<div class="col-sm-9">
<input id="packageregistryurl" class="form-control" @bind="@_packageregistryurl" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="packageregistryemail" HelpText="Specify The Email Address Of The User Account Used For Interacting With The Package Manager Service. This Account Is Used For Managing Packages Across Multiple Installations." ResourceKey="PackageManagerEmail">Package Manager Email: </Label>
<div class="col-sm-9">
<input id="packageregistryemail" class="form-control" @bind="@_packageregistryemail" />
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="osversion" HelpText="Operating System Version" ResourceKey="OSVersion">OS Version: </Label>
<div class="col-sm-9">
<input id="osversion" class="form-control" @bind="@_osversion" readonly />
<br /><br />
<button type="button" class="btn btn-success" @onclick="SaveConfig">@SharedLocalizer["Save"]</button>&nbsp;
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
<br /><br />
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Swagger"]</a>&nbsp;
<a class="btn btn-secondary" href="api/endpoint" target="_new">@Localizer["Endpoints"]</a>
</TabPanel>
<TabPanel Name="Log" Heading="Log" ResourceKey="Log">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="log" HelpText="System log information for current day" ResourceKey="Log">Log: </Label>
<div class="col-sm-9">
<textarea id="log" class="form-control" rows="10" @bind="@_log" readonly />
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="process" HelpText="Indicates if the current process is 32 bit or 64 bit" ResourceKey="Process">Process: </Label>
<div class="col-sm-9">
<input id="process" class="form-control" @bind="@_process" readonly />
<br /><br />
<button type="button" class="btn btn-danger" @onclick="ClearLog">@Localizer["Clear"]</button>
</TabPanel>
<TabPanel Name="Migrations" Heading="Migrations" ResourceKey="Migrations">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="tenant" HelpText="The name of the current database. Note that this is not the physical database name but rather the tenant name which is used within the framework to identify a database." ResourceKey="Tenant">Database: </Label>
<div class="col-sm-9">
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="machinename" HelpText="Machine Name" ResourceKey="MachineName">Machine Name: </Label>
<div class="col-sm-9">
<input id="machinename" class="form-control" @bind="@_machinename" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="ipaddress" HelpText="Server IP Address" ResourceKey="IPAddress">IP Address: </Label>
<div class="col-sm-9">
<input id="ipaddress" class="form-control" @bind="@_ipaddress" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="environment" HelpText="Environment name" ResourceKey="Environment">Environment: </Label>
<div class="col-sm-9">
<input id="environment" class="form-control" @bind="@_environment" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="contentrootpath" HelpText="Root Path" ResourceKey="ContentRootPath">Root Path: </Label>
<div class="col-sm-9">
<input id="contentrootpath" class="form-control" @bind="@_contentrootpath" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="webrootpath" HelpText="Web Path" ResourceKey="WebRootPath">Web Path: </Label>
<div class="col-sm-9">
<input id="webrootpath" class="form-control" @bind="@_webrootpath" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="servertime" HelpText="Server Date/Time (in UTC)" ResourceKey="ServerTime">Server Date/Time: </Label>
<div class="col-sm-9">
<input id="servertime" class="form-control" @bind="@_servertime" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="workingset" HelpText="Memory Allocation Of Service (in MB)" ResourceKey="WorkingSet">Memory Allocation: </Label>
<div class="col-sm-9">
<input id="workingset" class="form-control" @bind="@_workingset" readonly />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="installationid" HelpText="The Unique Identifier For Your Installation" ResourceKey="InstallationId">Installation ID: </Label>
<div class="col-sm-9">
<input id="installationid" class="form-control" @bind="@_installationid" readonly />
</div>
</div>
</div>
<br /><br />
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
</TabPanel>
<TabPanel Name="Options" Heading="Options" ResourceKey="Options">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="detailederrors" HelpText="Specify If Detailed Errors Are Enabled For Blazor. This Option Should Not Not Be Enabled In Production." ResourceKey="DetailedErrors">Detailed Errors? </Label>
<div class="col-sm-9">
<select id="detailederrors" class="form-select" @bind="@_detailederrors">
<option value="true">@SharedLocalizer["True"]</option>
<option value="false">@SharedLocalizer["False"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="logginglevel" HelpText="The Minimum Logging Level For The Event Log. This Option Can Be Used To Control The Volume Of Items Stored In Your Event Log." ResourceKey="LoggingLevel">Logging Level: </Label>
<div class="col-sm-9">
<select id="logginglevel" class="form-select" @bind="@_logginglevel">
<option value="Trace">@Localizer["Trace"]</option>
<option value="Debug">@Localizer["Debug"]</option>
<option value="Information">@Localizer["Information"]</option>
<option value="Warning">@Localizer["Warning"]</option>
<option value="Error">@Localizer["Error"]</option>
<option value="Critical">@Localizer["Critical"]</option>
<option value="None">@Localizer["None"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="notificationlevel" HelpText="The Minimum Logging Level For Which Notifications Should Be Sent To Host Users." ResourceKey="NotificationLevel">Notification Level: </Label>
<div class="col-sm-9">
<select id="notificationlevel" class="form-select" @bind="@_notificationlevel">
<option value="Trace">@Localizer["Trace"]</option>
<option value="Debug">@Localizer["Debug"]</option>
<option value="Information">@Localizer["Information"]</option>
<option value="Warning">@Localizer["Warning"]</option>
<option value="Error">@Localizer["Error"]</option>
<option value="Critical">@Localizer["Critical"]</option>
<option value="None">@Localizer["None"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="swagger" HelpText="Specify If Swagger Is Enabled For Your Server API" ResourceKey="Swagger">Swagger Enabled? </Label>
<div class="col-sm-9">
<select id="swagger" class="form-select" @bind="@_swagger">
<option value="true">@SharedLocalizer["True"]</option>
<option value="false">@SharedLocalizer["False"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="packageregistryurl" HelpText="Specify The Package Manager Service For Installing Modules, Themes, And Translations. If This Field Is Blank It Means The Package Manager Service Is Disabled For This Installation." ResourceKey="PackageManager">Package Manager: </Label>
<div class="col-sm-9">
<input id="packageregistryurl" class="form-control" @bind="@_packageregistryurl" />
</div>
</div>
</div>
<br /><br />
<button type="button" class="btn btn-success" @onclick="SaveConfig">@SharedLocalizer["Save"]</button>&nbsp;
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Access.ApiFramework"]</a>&nbsp;
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
</TabPanel>
<TabPanel Name="Log" Heading="Log" ResourceKey="Log">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="log" HelpText="System log information for current day" ResourceKey="Log">Log: </Label>
<div class="col-sm-9">
<textarea id="log" class="form-control" rows="10" @bind="@_log" readonly />
</div>
</div>
</div>
<br /><br />
<button type="button" class="btn btn-danger" @onclick="ClearLog">@Localizer["Clear"]</button>
</TabPanel>
</TabStrip>
<br /><br />
<br />
<Pager Items="@_history" SearchProperties="MigrationId">
<Header>
<th>@Localizer["Migration"]</th>
<th>@Localizer["Date"]</th>
<th>@Localizer["Version"]</th>
</Header>
<Row>
<td>@context.MigrationId</td>
<td>@UtcToLocal(context.AppliedDate)</td>
<td>@context.AppliedVersion</td>
</Row>
</Pager>
</TabPanel>
</TabStrip>
<br /><br />
}
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
private string _version = string.Empty;
private string _clrversion = string.Empty;
private string _osversion = string.Empty;
private bool _initialized = false;
private string _version = string.Empty;
private string _clrversion = string.Empty;
private string _osversion = string.Empty;
private string _process = string.Empty;
private string _machinename = string.Empty;
private string _ipaddress = string.Empty;
private string _environment = string.Empty;
private string _contentrootpath = string.Empty;
private string _webrootpath = string.Empty;
private string _servertime = string.Empty;
private string _workingset = string.Empty;
private string _installationid = string.Empty;
private string _ipaddress = string.Empty;
private string _environment = string.Empty;
private string _contentrootpath = string.Empty;
private string _webrootpath = string.Empty;
private string _servertime = string.Empty;
private string _workingset = string.Empty;
private string _installationid = string.Empty;
private string _detailederrors = string.Empty;
private string _logginglevel = string.Empty;
private string _notificationlevel = string.Empty;
private string _swagger = string.Empty;
private string _detailederrors = string.Empty;
private string _logginglevel = string.Empty;
private string _notificationlevel = string.Empty;
private string _swagger = string.Empty;
private string _cachecontrol = string.Empty;
private string _packageregistryurl = string.Empty;
private string _packageregistryemail = string.Empty;
private string _log = string.Empty;
private string _log = string.Empty;
protected override async Task OnInitializedAsync()
{
_version = Constants.Version;
private string _tenant = string.Empty;
private List<MigrationHistory> _history;
var systeminfo = await SystemService.GetSystemInfoAsync("environment");
if (systeminfo != null)
{
_clrversion = systeminfo["CLRVersion"].ToString();
_osversion = systeminfo["OSVersion"].ToString();
protected override async Task OnInitializedAsync()
{
_version = Constants.Version;
var systeminfo = await SystemService.GetSystemInfoAsync("environment");
if (systeminfo != null)
{
_clrversion = systeminfo["CLRVersion"].ToString();
_osversion = systeminfo["OSVersion"].ToString();
_process = systeminfo["Process"].ToString();
_machinename = systeminfo["MachineName"].ToString();
_ipaddress = systeminfo["IPAddress"].ToString();
_environment = systeminfo["Environment"].ToString();
_contentrootpath = systeminfo["ContentRootPath"].ToString();
_webrootpath = systeminfo["WebRootPath"].ToString();
_servertime = systeminfo["ServerTime"].ToString() + " UTC";
_workingset = (Convert.ToInt64(systeminfo["WorkingSet"].ToString()) / 1000000).ToString() + " MB";
}
_ipaddress = systeminfo["IPAddress"].ToString();
_environment = systeminfo["Environment"].ToString();
_contentrootpath = systeminfo["ContentRootPath"].ToString();
_webrootpath = systeminfo["WebRootPath"].ToString();
_servertime = systeminfo["ServerTime"].ToString() + " UTC";
_workingset = (Convert.ToInt64(systeminfo["WorkingSet"].ToString()) / 1000000).ToString() + " MB";
}
systeminfo = await SystemService.GetSystemInfoAsync("configuration");
if (systeminfo != null)
{
_installationid = systeminfo["InstallationId"].ToString();
_detailederrors = systeminfo["DetailedErrors"].ToString();
_logginglevel = systeminfo["Logging:LogLevel:Default"].ToString();
_notificationlevel = systeminfo["Logging:LogLevel:Notify"].ToString();
_swagger = systeminfo["UseSwagger"].ToString();
systeminfo = await SystemService.GetSystemInfoAsync("configuration");
if (systeminfo != null)
{
_installationid = systeminfo["InstallationId"].ToString();
_detailederrors = systeminfo["DetailedErrors"].ToString();
_logginglevel = systeminfo["Logging:LogLevel:Default"].ToString();
_notificationlevel = systeminfo["Logging:LogLevel:Notify"].ToString();
_swagger = systeminfo["UseSwagger"].ToString();
_cachecontrol = systeminfo["CacheControl"].ToString();
_packageregistryurl = systeminfo["PackageRegistryUrl"].ToString();
}
_packageregistryemail = systeminfo["PackageRegistryEmail"].ToString();
}
systeminfo = await SystemService.GetSystemInfoAsync("log");
if (systeminfo != null)
{
_log = systeminfo["Log"].ToString();
}
}
systeminfo = await SystemService.GetSystemInfoAsync("log");
if (systeminfo != null)
{
_log = systeminfo["Log"].ToString();
}
var tenants = await TenantService.GetTenantsAsync();
_tenant = tenants.Find(item => item.TenantId == PageState.Alias.TenantId).Name;
_history = await MigrationHistoryService.GetMigrationHistoryAsync();
_initialized = true;
}
private async Task SaveConfig()
{
@@ -229,8 +286,10 @@
settings.Add("Logging:LogLevel:Default", _logginglevel);
settings.Add("Logging:LogLevel:Notify", _notificationlevel);
settings.Add("UseSwagger", _swagger);
settings.Add("PackageRegistryUrl", _packageregistryurl);
await SystemService.UpdateSystemInfoAsync(settings);
settings.Add("CacheControl", _cachecontrol);
settings.Add("PackageRegistryUrl", _packageregistryurl);
settings.Add("PackageRegistryEmail", _packageregistryemail);
await SystemService.UpdateSystemInfoAsync(settings);
AddModuleMessage(Localizer["Success.UpdateConfig.Restart"], MessageType.Success);
}
catch (Exception ex)

View File

@@ -101,13 +101,20 @@
<small>@SharedLocalizer["Search.By"]:</small> <strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
<br />
@if (!string.IsNullOrEmpty(context.PackageUrl))
@if (_themes.Exists(item => item.PackageName == context.PackageId))
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
<button type="button" class="btn btn-info">@SharedLocalizer["Installed"]</button>
}
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
else
{
<a class="btn btn-success ms-2" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@SharedLocalizer["Buy"]</a>
@if (!string.IsNullOrEmpty(context.PackageUrl))
{
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
}
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
{
<a class="btn btn-success ms-2" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@SharedLocalizer["Buy"]</a>
}
}
<br />
</div>
@@ -125,7 +132,7 @@
<TabPanel Name="Upload" ResourceKey="Upload">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation." ResourceKey="Theme">Theme: </Label>
<Label Class="col-sm-3" HelpText="Upload one or more theme packages." ResourceKey="Theme">Theme: </Label>
<div class="col-sm-9">
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" OnUpload="OnUpload" />
</div>
@@ -171,6 +178,7 @@
@code {
private bool _initialized = false;
private List<Theme> _themes;
private int _page = 1;
private List<Package> _packages;
private string _price = "free";
@@ -187,7 +195,8 @@
{
try
{
await LoadThemes();
_themes = await ThemeService.GetThemesAsync(PageState.Site.SiteId);
await LoadPackages();
_initialized = true;
}
catch (Exception ex)
@@ -197,24 +206,10 @@
}
}
private async Task LoadThemes()
private async Task LoadPackages()
{
ShowProgressIndicator();
var themes = await ThemeService.GetThemesAsync();
ShowProgressIndicator();
_packages = await PackageService.GetPackagesAsync("theme", _search, _price, "", _sort);
if (_packages != null)
{
foreach (Package package in _packages.ToArray())
{
if (themes.Exists(item => item.PackageName == package.PackageId))
{
_packages.Remove(package);
}
}
}
HideProgressIndicator();
}
@@ -222,25 +217,25 @@
{
_price = price;
_sort = "popularity";
await LoadThemes();
await LoadPackages();
StateHasChanged();
}
private async Task Search()
{
await LoadThemes();
await LoadPackages();
}
private async Task Reset()
{
_page = 1;
_search = "";
await LoadThemes();
await LoadPackages();
}
private async Task Refresh()
{
await LoadThemes();
await LoadPackages();
}
private void OnPageChange(int page)
@@ -251,7 +246,7 @@
private async void SortChanged(ChangeEventArgs e)
{
_sort = (string)e.Value;
await LoadThemes();
await LoadPackages();
}
private void HideModal()
@@ -310,6 +305,6 @@
private void OnUpload()
{
AddModuleMessage(string.Format(Localizer["Success.Theme.Download"], NavigateUrl("admin/system")), MessageType.Success);
AddModuleMessage(string.Format(Localizer["Success.Theme.Upload"], NavigateUrl("admin/system")), MessageType.Success);
}
}

View File

@@ -1,6 +1,7 @@
@namespace Oqtane.Modules.Admin.Themes
@inherits ModuleBase
@using System.Text.RegularExpressions
@using System.Reflection
@inject NavigationManager NavigationManager
@inject IThemeService ThemeService
@inject IModuleService ModuleService
@@ -36,30 +37,33 @@
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
<div class="col-sm-9">
<select id="reference" class="form-select" @bind="@_reference">
@foreach (string version in _versions)
{
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
{
<option value="@(version)">@(version)</option>
}
}
<option value="local">@SharedLocalizer["LocalVersion"]</option>
</select>
</div>
</div>
@if (!string.IsNullOrEmpty(_location))
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="location" HelpText="Location where the theme will be created" ResourceKey="Location">Location: </Label>
<div class="col-sm-9">
<input id="module" class="form-control" @bind="@_location" readonly />
</div>
</div>
}
@if (_type == "External")
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
<div class="col-sm-9">
<select id="reference" class="form-select" @bind="@_reference">
@foreach (string version in _versions)
{
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
{
<option value="@(version)">@(version)</option>
}
}
<option value="local">@SharedLocalizer["LocalVersion"]</option>
</select>
</div>
</div>
@if (!string.IsNullOrEmpty(_location))
{
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="location" HelpText="Location where the theme will be created" ResourceKey="Location">Location: </Label>
<div class="col-sm-9">
<input id="module" class="form-control" @bind="@_location" readonly />
</div>
</div>
}
}
</div>
<br />
<button type="button" class="btn btn-success" @onclick="CreateTheme">@Localizer["Theme.Create"]</button>
@@ -71,9 +75,10 @@
private string _theme = string.Empty;
private List<Template> _templates;
private string _template = "-";
private string _minversion = "2.0.0";
private string _type = "";
private string[] _versions;
private string _reference = "local";
private string _minversion = "2.0.0";
private string _location = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
@@ -84,9 +89,19 @@
{
AddModuleMessage(Localizer["Info.Theme.CreatorIntent"], MessageType.Info);
}
else
{
var entryAssemblyName = Assembly.GetEntryAssembly().GetName().Name;
if (entryAssemblyName.EndsWith(".Oqtane"))
{
// Oqtane Application assemblies end with .Server.Oqtane or .Client.Oqtane
string[] segments = entryAssemblyName.Split('.');
_owner = string.Join(".", segments, 0, segments.Length - 2);
}
}
}
protected override async Task OnParametersSetAsync()
protected override async Task OnParametersSetAsync()
{
try
{
@@ -105,11 +120,18 @@
{
if (IsValid(_owner) && IsValid(_theme) && _owner != _theme && _template != "-")
{
if (_type == "Internal")
{
AddModuleMessage(Localizer["Success.Theme.Create.Internal"], MessageType.Success);
}
var template = _templates.FirstOrDefault(item => item.Name == _template);
var theme = new Theme { Owner = _owner, Name = _theme, Template = _template, Version = _reference, ThemeName = template.Namespace };
theme = await ThemeService.CreateThemeAsync(theme);
GetLocation();
AddModuleMessage(string.Format(Localizer["Success.Theme.Create"], NavigateUrl("admin/system")), MessageType.Success);
if (_type == "External")
{
GetLocation();
AddModuleMessage(string.Format(Localizer["Success.Theme.Create.External"], NavigateUrl("admin/system")), MessageType.Success);
}
}
else
{
@@ -125,17 +147,22 @@
private bool IsValid(string name)
{
// must contain letters, underscores and digits and first character must be letter or underscore
return !string.IsNullOrEmpty(name) && name.ToLower() != "theme" && !name.ToLower().Contains("oqtane") && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
return !string.IsNullOrEmpty(name) && name.ToLower() != "theme" && !name.ToLower().Contains("oqtane") && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_.]*$");
}
private void TemplateChanged(ChangeEventArgs e)
{
_template = (string)e.Value;
_minversion = "2.0.0";
if (_template != "-")
{
var template = _templates.FirstOrDefault(item => item.Name == _template);
_minversion = template.Version;
_type = template.Type;
}
else
{
_minversion = "2.0.0";
_type = "";
}
GetLocation();
}

View File

@@ -9,101 +9,98 @@
@if (_initialized)
{
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="The name of the module" ResourceKey="Name">Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" />
<TabStrip>
<TabPanel Name="Theme" ResourceKey="Theme" Heading="Theme">
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="The name of the theme" ResourceKey="Name">Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="isenabled" HelpText="Is theme enabled for this site?" ResourceKey="IsEnabled">Enabled? </Label>
<div class="col-sm-9">
<select id="isenabled" class="form-select" @bind="@_isenabled" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="isenabled" HelpText="Is theme enabled for this site?" ResourceKey="IsEnabled">Enabled? </Label>
<div class="col-sm-9">
<select id="isenabled" class="form-select" @bind="@_isenabled" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
</div>
</form>
<Section Name="Information" ResourceKey="Information" Heading="Information">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="themename" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
<div class="col-sm-9">
<input id="themename" class="form-control" @bind="@_themeName" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="version" HelpText="The version of the theme" ResourceKey="Version">Version: </Label>
<div class="col-sm-9">
<input id="version" class="form-control" @bind="@_version" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="packagename" HelpText="The unique name of the package from which this theme was installed. This value must be specified within the theme's ITheme interface specification." ResourceKey="PackageName">Package Name: </Label>
<div class="col-sm-9">
@if (!string.IsNullOrEmpty(_packagename))
{
<div class="input-group">
</form>
<Section Name="Information" ResourceKey="Information" Heading="Information">
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="themename" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
<div class="col-sm-9">
<input id="themename" class="form-control" @bind="@_themeName" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="version" HelpText="The version of the theme" ResourceKey="Version">Version: </Label>
<div class="col-sm-9">
<input id="version" class="form-control" @bind="@_version" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="packagename" HelpText="The unique name of the package from which this theme was installed. This value must be specified within the theme's ITheme interface specification." ResourceKey="PackageName">Package Name: </Label>
<div class="col-sm-9">
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
@if (string.IsNullOrEmpty(_packageurl))
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the theme" ResourceKey="Owner">Owner: </Label>
<div class="col-sm-9">
<input id="owner" class="form-control" @bind="@_owner" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="url" HelpText="The url of the theme" ResourceKey="Url">Url: </Label>
<div class="col-sm-9">
<input id="url" class="form-control" @bind="@_url" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="contact" HelpText="The contact for the theme" ResourceKey="Contact">Contact: </Label>
<div class="col-sm-9">
<input id="contact" class="form-control" @bind="@_contact" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="license" HelpText="The license of the theme" ResourceKey="License">License: </Label>
<div class="col-sm-9">
@if (_license.StartsWith("http") || _license.StartsWith("/") || _license.StartsWith("~"))
{
<button type="button" class="btn btn-secondary" @onclick="ValidatePackage">@Localizer["Validate"]</button>
<a href="@_license.Replace("~", PageState?.Alias.BaseUrl + "/Themes/" + Utilities.GetTypeName(_themeName))" class="btn btn-info" style="text-decoration: none !important" target="_new">@Localizer["View License"]</a>
}
else
{
<a href="@_packageurl" target="_blank" class="btn btn-primary">@SharedLocalizer["Download"]</a>
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
}
</div>
}
else
{
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
}
</div>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the theme" ResourceKey="Owner">Owner: </Label>
<div class="col-sm-9">
<input id="owner" class="form-control" @bind="@_owner" disabled />
</Section>
<br />
<button type="button" class="btn btn-success" @onclick="SaveTheme">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
<br />
<br />
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
</TabPanel>
<TabPanel Name="Permissions" ResourceKey="Permissions" Heading="Permissions">
<div class="container">
<div class="row mb-1 align-items-center">
<PermissionGrid EntityName="@EntityNames.Theme" PermissionNames="@PermissionNames.Utilize" PermissionList="@_permissions" @ref="_permissionGrid" />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="url" HelpText="The reference url of the theme" ResourceKey="ReferenceUrl">Reference Url: </Label>
<div class="col-sm-9">
<input id="url" class="form-control" @bind="@_url" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="contact" HelpText="The contact for the theme" ResourceKey="Contact">Contact: </Label>
<div class="col-sm-9">
<input id="contact" class="form-control" @bind="@_contact" disabled />
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="license" HelpText="The license of the theme" ResourceKey="License">License: </Label>
<div class="col-sm-9">
@if (_license.StartsWith("http") || _license.StartsWith("/") || _license.StartsWith("~"))
{
<a href="@_license.Replace("~", PageState?.Alias.BaseUrl + "/Themes/" + Utilities.GetTypeName(_themeName))" class="btn btn-info" style="text-decoration: none !important" target="_new">@Localizer["View License"]</a>
}
else
{
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
}
</div>
</div>
</div>
</Section>
<br />
<button type="button" class="btn btn-success" @onclick="SaveTheme">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
<br />
<br />
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
<br />
<button type="button" class="btn btn-success" @onclick="SaveTheme">@SharedLocalizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
</TabPanel>
</TabStrip>
}
@code {
@@ -116,16 +113,18 @@
private string _name;
private string _version;
private string _packagename = "";
private string _packageurl = "";
private string _owner = "";
private string _url = "";
private string _contact = "";
private string _license = "";
private List<Permission> _permissions = null;
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
private PermissionGrid _permissionGrid;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnInitializedAsync()
@@ -144,6 +143,7 @@
_url = theme.Url;
_contact = theme.Contact;
_license = theme.License;
_permissions = theme.PermissionList;
_createdby = theme.CreatedBy;
_createdon = theme.CreatedOn;
_modifiedby = theme.ModifiedBy;
@@ -170,6 +170,7 @@
var theme = await ThemeService.GetThemeAsync(_themeId, ModuleState.SiteId);
theme.Name = _name;
theme.IsEnabled = (_isenabled == null ? true : bool.Parse(_isenabled));
theme.PermissionList = _permissionGrid.GetPermissionList();
await ThemeService.UpdateThemeAsync(theme);
await logger.LogInformation("Theme Saved {Theme}", theme);
NavigationManager.NavigateTo(NavigateUrl());
@@ -185,27 +186,4 @@
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
}
}
private async Task ValidatePackage()
{
try
{
var package = await PackageService.GetPackageAsync(_packagename, _version, true);
if (package == null || string.IsNullOrEmpty(package.PackageUrl))
{
AddModuleMessage(Localizer["Message.Validate"], MessageType.Warning);
}
else
{
_packageurl = package.PackageUrl;
AddModuleMessage(Localizer["Message.Download"], MessageType.Info);
}
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packagename, _version);
AddModuleMessage(Localizer["Error.Validate"], MessageType.Error);
}
}
}

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