();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.GoogleMaps/ViewModels/GoogleMapPartViewModel.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc.ModelBinding;
2 | using OrchardCore.ContentManagement;
3 | using OrchardCoreContrib.GoogleMaps.Models;
4 | using System;
5 |
6 | namespace OrchardCoreContrib.GoogleMaps.ViewModels
7 | {
8 | public class GoogleMapPartViewModel
9 | {
10 | public double Latitude { get; set; }
11 |
12 | public double Longitude { get; set; }
13 |
14 | [BindNever]
15 | public ContentItem ContentItem { get; set; }
16 |
17 | [BindNever]
18 | public GoogleMapPart GoogleMapPart { get; set; }
19 |
20 | [BindNever]
21 | public GoogleMapsSettings Settings { get; set; }
22 |
23 | public bool DevelopmentMode => String.IsNullOrEmpty(Settings.ApiKey);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.GoogleMaps/ViewModels/GoogleMapsSettingsViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace OrchardCoreContrib.GoogleMaps.ViewModels
4 | {
5 | public class GoogleMapsSettingsViewModel
6 | {
7 | public string ApiKey { get; set; }
8 |
9 | [Required]
10 | public double Latitude { get; set; }
11 |
12 | [Required]
13 | public double Longitude { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.GoogleMaps/Views/GoogleMapPart.Edit.cshtml:
--------------------------------------------------------------------------------
1 | @using OrchardCoreContrib.GoogleMaps.ViewModels
2 | @model GoogleMapPartViewModel
3 |
4 |
5 | @T["Latitude"]
6 |
7 |
8 |
9 |
10 |
11 | @T["Longitude"]
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.GoogleMaps/Views/GoogleMapPart.cshtml:
--------------------------------------------------------------------------------
1 | @using OrchardCoreContrib.GoogleMaps
2 | @using OrchardCoreContrib.GoogleMaps.ViewModels
3 | @model GoogleMapPartViewModel
4 |
5 | @{
6 | var queryString = Model.DevelopmentMode
7 | ? $"callback=loadMap"
8 | : $"key={Model.Settings.ApiKey}&callback=loadMap";
9 | }
10 |
11 |
12 |
13 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.GoogleMaps/Views/GoogleMapsSettings.Edit.cshtml:
--------------------------------------------------------------------------------
1 | @using OrchardCoreContrib.GoogleMaps.ViewModels
2 | @model GoogleMapsSettingsViewModel
3 |
4 |
5 | @T["API Key"]
6 |
7 | @T["The API key for authentication. If you left the API key empty, the map will be for development purposes only."]
8 |
9 |
10 |
11 | @T["Latitude"]
12 |
13 |
14 |
15 |
16 |
17 | @T["Longitude"]
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.GoogleMaps/Views/NavigationItemText-googlemaps.Id.cshtml:
--------------------------------------------------------------------------------
1 | @T["Google Maps"]
2 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.GoogleMaps/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @inherits OrchardCore.DisplayManagement.Razor.RazorPage
2 |
3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
4 | @addTagHelper *, OrchardCore.DisplayManagement
5 | @addTagHelper *, OrchardCore.ResourceManagement
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Gravatar/GravatarConstants.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.Gravatar;
2 |
3 | public class GravatarConstants
4 | {
5 | public const int DefaultSize = 80;
6 | }
7 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Gravatar/GravatarOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 |
4 | namespace OrchardCoreContrib.Gravatar;
5 |
6 | public class GravatarOptions
7 | {
8 | public string DefaultImage { get; set; }
9 |
10 | public GravatarRating Rating { get; set; } = GravatarRating.PG;
11 |
12 | [Range(1, 512)]
13 | [Obsolete("This property has been deprecated.")]
14 | public int Size { get; set; } = GravatarConstants.DefaultSize;
15 | }
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Gravatar/GravatarRating.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.Gravatar;
2 |
3 | public enum GravatarRating
4 | {
5 | G,
6 | PG,
7 | R,
8 | X
9 | }
10 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Gravatar/Liquid/GravatarFilter.cs:
--------------------------------------------------------------------------------
1 | using Fluid;
2 | using Fluid.Values;
3 | using OrchardCore.Liquid;
4 | using OrchardCoreContrib.Gravatar.Services;
5 | using System.Threading.Tasks;
6 |
7 | namespace OrchardCoreContrib.Gravatar.Liquid;
8 |
9 | public class GravatarFilter : ILiquidFilter
10 | {
11 | private readonly IGravatarService _gravatarService;
12 |
13 | public GravatarFilter(IGravatarService gravatarService)
14 | {
15 | _gravatarService = gravatarService;
16 | }
17 |
18 | public ValueTask ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context)
19 | {
20 | var email = input.ToStringValue();
21 |
22 | if (input.IsNil())
23 | {
24 | return NilValue.Empty;
25 | }
26 | else
27 | {
28 | var size = GravatarConstants.DefaultSize;
29 | if (arguments.Count == 1)
30 | {
31 | size = (int)arguments["size"].ToNumberValue();
32 | }
33 |
34 | var gravatarUrl = _gravatarService.GetAvatarUrl(email, size);
35 |
36 | return FluidValue.Create(gravatarUrl, context.Options);
37 | }
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Gravatar/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "Gravatar",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.4.1",
9 | Category = "Profile",
10 | Description = "The gravatar module enables user avatar using gravatar service.",
11 | Dependencies = new[] { "OrchardCore.Users" }
12 | )]
13 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Gravatar/Services/IGravatarService.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.Gravatar.Services;
2 |
3 | public interface IGravatarService
4 | {
5 | string GetAvatarUrl(string email, int size = GravatarConstants.DefaultSize);
6 | }
7 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Gravatar/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using OrchardCore.Environment.Shell.Configuration;
3 | using OrchardCore.Liquid;
4 | using OrchardCore.Modules;
5 | using OrchardCoreContrib.Gravatar.Liquid;
6 | using OrchardCoreContrib.Gravatar.Services;
7 | using OrchardCoreContrib.Gravatar.TagHelpers;
8 |
9 | namespace OrchardCoreContrib.Gravatar;
10 |
11 | ///
12 | /// Represents an entry point to register the user avatar required services.
13 | ///
14 | public class Startup : StartupBase
15 | {
16 | private readonly IShellConfiguration _shellConfiguration;
17 |
18 | public Startup(IShellConfiguration shellConfiguration)
19 | {
20 | _shellConfiguration = shellConfiguration;
21 | }
22 |
23 | ///
24 | public override void ConfigureServices(IServiceCollection services)
25 | {
26 | services.AddScoped();
27 |
28 | services.AddTagHelpers();
29 |
30 | services.AddLiquidFilter("gravatar_url");
31 |
32 | services.Configure(_shellConfiguration.GetSection("OrchardCoreContrib_Gravatar"));
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Gravatar/TagHelpers/GravatarTagHelper.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Razor.TagHelpers;
2 | using OrchardCoreContrib.Gravatar.Services;
3 | using System;
4 | using System.ComponentModel.DataAnnotations;
5 |
6 | namespace OrchardCoreContrib.Gravatar.TagHelpers;
7 |
8 | [HtmlTargetElement("gravatar", TagStructure = TagStructure.NormalOrSelfClosing)]
9 | public class GravatarTagHelper : TagHelper
10 | {
11 | private readonly IGravatarService _gravatarService;
12 |
13 | public GravatarTagHelper(IGravatarService gravatarService)
14 | {
15 | _gravatarService = gravatarService;
16 | }
17 |
18 | public string Email { get; set; }
19 |
20 | [Range(1, 512)]
21 | public int Size { get; set; } = GravatarConstants.DefaultSize;
22 |
23 | public override void Process(TagHelperContext context, TagHelperOutput output)
24 | {
25 | output.TagName = "img";
26 |
27 | var avatarUrl = _gravatarService.GetAvatarUrl(Email, Size);
28 |
29 | output.Attributes.Add("src", avatarUrl);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Gravatar/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @inherits OrchardCore.DisplayManagement.Razor.RazorPage
2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
3 | @addTagHelper *, OrchardCore.DisplayManagement
4 | @addTagHelper *, OrchardCore.ResourceManagement
5 | @addTagHelper *, OrchardCoreContrib.Gravatar
6 |
7 | @using Microsoft.Extensions.Localization;
8 | @using Microsoft.AspNetCore.Mvc.Localization;
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.HealthChecks/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "Health Checks",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.2.1",
9 | Description = "Provides health checks for the website.",
10 | Category = "Infrastructure"
11 | )]
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/Controllers/AdminController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using OrchardCore.Modules;
3 |
4 | namespace OrchardCoreContrib.Html.Controllers
5 | {
6 | [Feature("OrchardCoreContrib.Html.GrapesJS")]
7 | public class AdminController : Controller
8 | {
9 | [HttpGet]
10 | public ActionResult Index() => View();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "Html",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.2.1"
9 | )]
10 |
11 | [assembly: Feature(
12 | Id = "OrchardCoreContrib.Html.GrapesJS",
13 | Name = "GrapesJS HTML Editor",
14 | Description = "Enables GrapesJS editor for HtmlBody content.",
15 | Dependencies = new[] { "OrchardCore.Html" },
16 | Category = "Content Management"
17 | )]
18 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Builder;
3 | using Microsoft.AspNetCore.Routing;
4 | using OrchardCore.Modules;
5 | using OrchardCore.Mvc.Core.Utilities;
6 | using OrchardCoreContrib.Html.Controllers;
7 |
8 | namespace OrchardCoreContrib.Html
9 | {
10 | [Feature("OrchardCoreContrib.Html.GrapesJS")]
11 | public class Startup : StartupBase
12 | {
13 | public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
14 | {
15 | routes.MapAreaControllerRoute(
16 | name: "GrapesJSEditor",
17 | areaName: "OrchardCoreContrib.Html",
18 | pattern: "GrapesJSEditor",
19 | defaults: new { controller = typeof(AdminController).ControllerName(), action = nameof(AdminController.Index) }
20 | );
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/Views/Admin/Index.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = null;
3 | }
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/Views/HtmlBodyPart-GrapeJS.Edit.cshtml:
--------------------------------------------------------------------------------
1 | @model HtmlBodyPartViewModel
2 |
3 |
4 | @Model.TypePartDefinition.DisplayName()
5 |
6 |
7 |
9 | @T["The body of the content item."]
10 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/Views/HtmlBodyPart-GrapeJS.Option.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | string currentEditor = Model.Editor;
3 | }
4 | @T["GrapeJS editor"]
5 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @inherits OrchardCore.DisplayManagement.Razor.RazorPage
2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
3 | @addTagHelper *, OrchardCore.DisplayManagement
4 | @addTagHelper *, OrchardCore.ResourceManagement
5 | @using OrchardCore.ContentManagement.Metadata.Models
6 | @using OrchardCore.DisplayManagement
7 | @using OrchardCore.Html.ViewModels
8 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/wwwroot/Styles/grapes-editor.css:
--------------------------------------------------------------------------------
1 | .grapes-editor {
2 | border: 3px solid #444;
3 | }
4 |
5 | .gjs_override * {
6 | box-sizing: content-box !important;
7 | }
8 |
9 | .gjs-mdl-content pre {
10 | color: white !important;
11 | }
12 |
13 | body {
14 | margin: 0;
15 | }
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/wwwroot/Styles/grapesjs-preset-webpage.min.css:
--------------------------------------------------------------------------------
1 | .gjs-one-bg{background-color:#463a3c}.gjs-one-color{color:#463a3c}.gjs-one-color-h:hover{color:#463a3c}.gjs-two-bg{background-color:#b9a5a6}.gjs-two-color{color:#b9a5a6}.gjs-two-color-h:hover{color:#b9a5a6}.gjs-three-bg{background-color:#804f7b}.gjs-three-color{color:#804f7b}.gjs-three-color-h:hover{color:#804f7b}.gjs-four-bg{background-color:#d97aa6}.gjs-four-color{color:#d97aa6}.gjs-four-color-h:hover{color:#d97aa6}
2 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Html/wwwroot/fonts/main-fonts.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Html/wwwroot/fonts/main-fonts.woff
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Liquid/Environment.cs:
--------------------------------------------------------------------------------
1 | using Fluid.Values;
2 |
3 | namespace OrchardCoreContrib.Liquid;
4 |
5 | public class Environment
6 | {
7 | public BooleanValue IsDevelopment { get; set; }
8 |
9 | public BooleanValue IsStaging { get; set; }
10 |
11 | public BooleanValue IsProduction { get; set; }
12 | }
13 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Liquid/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "Liquid",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.2.1",
9 | Description = "Provides a list of useful liquid filters.",
10 | Category = "Content Management"
11 | )]
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Liquid/Startup.cs:
--------------------------------------------------------------------------------
1 | using Fluid;
2 | using Fluid.Values;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using Microsoft.Extensions.Hosting;
5 | using OrchardCore.Modules;
6 |
7 | namespace OrchardCoreContrib.Liquid;
8 | public class Startup : StartupBase
9 | {
10 | private readonly IHostEnvironment _hostEnvironment;
11 |
12 | public Startup(IHostEnvironment hostEnvironment)
13 | {
14 | _hostEnvironment = hostEnvironment;
15 | }
16 |
17 | public override void ConfigureServices(IServiceCollection services)
18 | {
19 | var environment = new Environment
20 | {
21 | IsDevelopment = BooleanValue.Create(_hostEnvironment.IsDevelopment()),
22 | IsStaging = BooleanValue.Create(_hostEnvironment.IsStaging()),
23 | IsProduction = BooleanValue.Create(_hostEnvironment.IsProduction())
24 | };
25 |
26 | services.Configure(options =>
27 | {
28 | options.Scope.SetValue("Environment", new ObjectValue(environment));
29 |
30 | options.MemberAccessStrategy.Register();
31 | });
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Modules.Web/MigrationUpdater.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Environment.Extensions.Features;
2 | using OrchardCore.Environment.Shell;
3 | using OrchardCoreContrib.Data.Migrations;
4 | using System.Threading.Tasks;
5 |
6 | namespace OrchardCoreContrib.Modules.Web;
7 |
8 | public class MigrationUpdater : IFeatureEventHandler
9 | {
10 | private readonly IMigrationRunner _migrationRunner;
11 |
12 | public MigrationUpdater(IMigrationRunner migrationRunner)
13 | {
14 | _migrationRunner = migrationRunner;
15 | }
16 |
17 | public Task DisabledAsync(IFeatureInfo feature) => Task.CompletedTask;
18 |
19 | public Task DisablingAsync(IFeatureInfo feature) => Task.CompletedTask;
20 |
21 | public Task EnabledAsync(IFeatureInfo feature) => Task.CompletedTask;
22 |
23 | public Task EnablingAsync(IFeatureInfo feature) => Task.CompletedTask;
24 |
25 | public async Task InstalledAsync(IFeatureInfo feature)
26 | => await _migrationRunner.MigrateAsync(feature.Extension.Manifest.ModuleInfo.Id);
27 |
28 | public Task InstallingAsync(IFeatureInfo feature) => Task.CompletedTask;
29 |
30 | public async Task UninstalledAsync(IFeatureInfo feature)
31 | => await _migrationRunner.RollbackAsync(feature.Extension.Manifest.ModuleInfo.Id);
32 |
33 | public Task UninstallingAsync(IFeatureInfo feature) => Task.CompletedTask;
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Modules.Web/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Hosting;
2 | using Microsoft.Extensions.Hosting;
3 |
4 | namespace OrchardCoreContrib.Modules.Web
5 | {
6 | public class Program
7 | {
8 | public static void Main(string[] args)
9 | {
10 | CreateHostBuilder(args).Build().Run();
11 | }
12 |
13 | public static IHostBuilder CreateHostBuilder(string[] args) =>
14 | Host.CreateDefaultBuilder(args)
15 | .ConfigureWebHostDefaults(webBuilder =>
16 | {
17 | webBuilder.UseStartup();
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Modules.Web/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:51842",
7 | "sslPort": 44375
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "OrchardCoreContrib.Modules.Web": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
22 | "environmentVariables": {
23 | "ASPNETCORE_ENVIRONMENT": "Development"
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Modules.Web/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using Microsoft.Extensions.Hosting;
5 | using OrchardCore.Environment.Shell;
6 | using OrchardCoreContrib.Users.Services;
7 |
8 | namespace OrchardCoreContrib.Modules.Web
9 | {
10 | public class Startup
11 | {
12 | public void ConfigureServices(IServiceCollection services)
13 | {
14 | services
15 | .AddOrchardCms(builder =>
16 | {
17 | builder.AddSetupFeatures("OrchardCore.AutoSetup", "OrchardCoreContrib.Tenants");
18 | //builder.ConfigureServices(builderServices =>
19 | //{
20 | // builderServices.AddYesSqlDataMigrations();
21 |
22 | // builderServices.AddScoped();
23 | // builderServices.AddScoped(sp => sp.GetRequiredService());
24 | //});
25 | });
26 |
27 | // Workaround to avoid IOE on UserMenu shape
28 | services.AddScoped();
29 | }
30 |
31 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
32 | {
33 | if (env.IsDevelopment())
34 | {
35 | app.UseDeveloperExceptionPage();
36 | }
37 |
38 | app.UseOrchardCore();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Modules.Web/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Modules.Web/wwwroot/.placeholder:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Modules.Web/wwwroot/.placeholder
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ReverseProxy.Yarp/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "Yet Another Reverse Proxy (YARP)",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.2.1",
9 | Description = "Enables configuration of hosting scenarios with a reverse proxy using YARP",
10 | Category = "Infrastructure"
11 | )]
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ReverseProxy.Yarp/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Routing;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using OrchardCore.Environment.Shell.Configuration;
5 | using OrchardCore.Modules;
6 | using System;
7 |
8 | namespace OrchardCoreContrib.ReverseProxy.Yarp;
9 |
10 | public class Startup : StartupBase
11 | {
12 | private readonly IShellConfiguration _shellConfiguration;
13 |
14 | public Startup(IShellConfiguration shellConfiguration)
15 | {
16 | _shellConfiguration = shellConfiguration;
17 | }
18 |
19 | public override int Order => -1;
20 |
21 | public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
22 | {
23 | routes.MapReverseProxy();
24 | }
25 |
26 | public override void ConfigureServices(IServiceCollection services)
27 | {
28 | services
29 | .AddReverseProxy()
30 | .LoadFromConfig(_shellConfiguration.GetSection("OrchardCoreContrib_Yarp"));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/AdminMenu.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Routing;
2 | using Microsoft.Extensions.Localization;
3 | using OrchardCore.Navigation;
4 | using OrchardCoreContrib.Navigation;
5 | using OrchardCoreContrib.Sms.Azure.Drivers;
6 |
7 | namespace OrchardCoreContrib.Sms.Azure;
8 |
9 | using OrchardCoreContrib.Navigation;
10 |
11 | public class AdminMenu(IStringLocalizer S) : AdminNavigationProvider
12 | {
13 | private static readonly RouteValueDictionary _routeValues = new()
14 | {
15 | { "area", "OrchardCore.Settings" },
16 | { "groupId", AzureSmsSettingsDisplayDriver.GroupId },
17 | };
18 |
19 | public override void BuildNavigation(NavigationBuilder builder)
20 | {
21 | builder
22 | .Add(S["Configuration"], configuration => configuration
23 | .Add(S["Settings"], settings => settings
24 | .Add(S["Azure SMS"], S["Azure SMS"].PrefixPosition(), sms => sms
25 | .AddClass("azure-sms").Id("azuresms")
26 | .Action("Index", "Admin", _routeValues)
27 | .Permission(AzureSmsPermissions.ManageSettings)
28 | .LocalNav()
29 | )
30 | )
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/AzureSmsPermissionProvider.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Security.Permissions;
2 |
3 | namespace OrchardCoreContrib.Sms.Azure;
4 |
5 | public class AzureSmsPermissionProvider : IPermissionProvider
6 | {
7 | private static readonly IEnumerable _permissions = [AzureSmsPermissions.ManageSettings];
8 |
9 | public Task> GetPermissionsAsync() => Task.FromResult(_permissions);
10 |
11 | public IEnumerable GetDefaultStereotypes() =>
12 | [
13 | new PermissionStereotype
14 | {
15 | Name = "Administrator",
16 | Permissions = _permissions,
17 | }
18 | ];
19 | }
20 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/AzureSmsPermissions.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Security.Permissions;
2 |
3 | namespace OrchardCoreContrib.Sms.Azure;
4 |
5 | public class AzureSmsPermissions
6 | {
7 | public static readonly Permission ManageSettings = new("ManageSettings", "Manage Azure SMS Settings");
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/AzureSmsSettings.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.Sms.Azure;
2 |
3 | public class AzureSmsSettings
4 | {
5 | public string ConnectionString { get; set; }
6 |
7 | public string SenderPhoneNumber { get; set; }
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "Azure SMS",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.0.1",
9 | Description = "Provides settings and services to send SMS messages using Azure Communication Service.",
10 | Category = "Messaging"
11 | )]
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/Services/AzureSmsService.cs:
--------------------------------------------------------------------------------
1 | using Azure.Communication.Sms;
2 | using Microsoft.Extensions.Localization;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.Options;
5 | using OrchardCoreContrib.Infrastructure;
6 |
7 | namespace OrchardCoreContrib.Sms.Azure.Services;
8 |
9 | public class AzureSmsService(
10 | IOptions azureSmsOptions,
11 | ILogger logger,
12 | IStringLocalizer S) : ISmsService
13 | {
14 | private readonly AzureSmsSettings _azureSmsOptions = azureSmsOptions.Value;
15 | private readonly ILogger _logger = logger;
16 |
17 | public async Task SendAsync(SmsMessage message)
18 | {
19 | Guard.ArgumentNotNull(message, nameof(message));
20 |
21 | _logger.LogDebug("Attempting to send SMS to {PhoneNumber}.", message.PhoneNumber);
22 |
23 | try
24 | {
25 | var client = new SmsClient(_azureSmsOptions.ConnectionString);
26 | var smsResult = await client.SendAsync(_azureSmsOptions.SenderPhoneNumber, message.PhoneNumber, message.Text);
27 |
28 | return SmsResult.Success;
29 | }
30 | catch (Exception ex)
31 | {
32 | _logger.LogError(ex, "An error occurred while sending an SMS using the Azure SMS.");
33 |
34 | return SmsResult.Failed(S["An error occurred while sending an SMS."]);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/ViewModels/AzureSmsSettingsViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace OrchardCoreContrib.Sms.Azure.ViewModels;
4 |
5 | public class AzureSmsSettingsViewModel
6 | {
7 | [Required]
8 | public string PhoneNumber { get; set; }
9 |
10 | [Required]
11 | public string Message { get; set; }
12 | }
13 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/Views/Admin/Index.cshtml:
--------------------------------------------------------------------------------
1 | @using OrchardCoreContrib.Sms.Azure.ViewModels
2 | @model AzureSmsSettingsViewModel
3 |
4 | @RenderTitleSegments(T["Test Azure SMS Settings"])
5 |
6 |
23 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/Views/AzureSmsSettings.Edit.cshtml:
--------------------------------------------------------------------------------
1 | @using OrchardCoreContrib.Sms.Azure
2 |
3 | @model AzureSmsSettings
4 |
5 | @T["The current tenant will be reloaded when the settings are saved."]
6 |
7 |
8 | @T["Sender Phone Number"]
9 |
10 | @T["The phone number that provided by Azure Communication Services (ACS) to send the SMS."]
11 |
12 |
13 |
14 |
15 | @T["Connection String"]
16 |
17 |
18 | @T["The connection string that provided by Azure Communication Services (ACS)."]
19 |
20 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/Views/AzureSmsSettings.TestButton.cshtml:
--------------------------------------------------------------------------------
1 | @T["Test settings"]
2 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/Views/NavigationItemText-azuresms.Id.cshtml:
--------------------------------------------------------------------------------
1 | @T["Azure SMS"]
2 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Sms.Azure/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @inherits OrchardCore.DisplayManagement.Razor.RazorPage
2 |
3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
4 | @addTagHelper *, OrchardCore.DisplayManagement
5 | @addTagHelper *, OrchardCore.ResourceManagement
6 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/AdminMenu.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Localization;
2 | using OrchardCore.Navigation;
3 | using OrchardCoreContrib.Navigation;
4 |
5 | namespace OrchardCoreContrib.System;
6 |
7 | using OrchardCoreContrib.Navigation;
8 |
9 | ///
10 | /// Represents an admin menu for System module.
11 | ///
12 | public class AdminMenu : AdminNavigationProvider
13 | {
14 | private readonly IStringLocalizer S;
15 |
16 | ///
17 | /// Initializes a new instance of .
18 | ///
19 | /// The .
20 | public AdminMenu(IStringLocalizer stringLocalizer)
21 | {
22 | S = stringLocalizer;
23 | }
24 |
25 | ///
26 | public override void BuildNavigation(NavigationBuilder builder)
27 | {
28 | builder.Add(S["System"], "100", info => info
29 | .AddClass("system").Id("system")
30 | .Add(S["Info"], S["Info"].PrefixPosition(), updates => updates
31 | .AddClass("info").Id("info")
32 | .Action("About", "Admin", "OrchardCoreContrib.System")
33 | .LocalNav())
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Extensions/ApplicationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Logging;
3 | using Microsoft.Extensions.Options;
4 | using OrchardCore.Admin;
5 | using OrchardCore.ContentManagement.Routing;
6 | using OrchardCore.Settings;
7 | using OrchardCore.Users;
8 | using OrchardCoreContrib.System.Services;
9 |
10 | namespace Microsoft.AspNetCore.Builder;
11 |
12 | public static class ApplicationBuilderExtensions
13 | {
14 | public static IApplicationBuilder UseMaintenanceRedirect(this IApplicationBuilder app)
15 | {
16 | if (app == null)
17 | {
18 | throw new ArgumentNullException(nameof(app));
19 | }
20 |
21 | var siteService = app.ApplicationServices.GetService();
22 | var adminOptions = app.ApplicationServices.GetService>();
23 | var userOptions = app.ApplicationServices.GetService>();
24 | var autorouteEntries = app.ApplicationServices.GetService();
25 | var logger = app.ApplicationServices.GetService>();
26 |
27 | return app.UseMiddleware(siteService, adminOptions, userOptions, autorouteEntries, logger);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/HealthChecks/Extensions/SystemUpdatesHealthCheckExtensions.cs:
--------------------------------------------------------------------------------
1 | using OrchardCoreContrib.System.HealthChecks;
2 |
3 | namespace Microsoft.Extensions.DependencyInjection;
4 |
5 | public static class SystemUpdatesHealthCheckExtensions
6 | {
7 | public static IHealthChecksBuilder AddSystemUpdatesCheck(this IHealthChecksBuilder healthChecksBuilder)
8 | => healthChecksBuilder.AddCheck(SystemUpdatesHealthCheck.Name);
9 | }
10 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/HealthChecks/SystemUpdatesHealthCheck.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Diagnostics.HealthChecks;
2 | using Microsoft.Extensions.Localization;
3 | using OrchardCoreContrib.System.Services;
4 |
5 | namespace OrchardCoreContrib.System.HealthChecks;
6 |
7 | public class SystemUpdatesHealthCheck : IHealthCheck
8 | {
9 | internal const string Name = "System Updates Health Check";
10 |
11 | private readonly SystemInformation _systemInformation;
12 | private readonly ISystemUpdateService _systemUpdateService;
13 | private readonly IStringLocalizer S;
14 |
15 | public SystemUpdatesHealthCheck(
16 | SystemInformation systemInformation,
17 | ISystemUpdateService systemUpdateService,
18 | IStringLocalizer stringLocalizer)
19 | {
20 | _systemInformation = systemInformation;
21 | _systemUpdateService = systemUpdateService;
22 | S = stringLocalizer;
23 | }
24 |
25 | public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
26 | {
27 | var updates = await _systemUpdateService.GetUpdatesAsync();
28 |
29 | var updatesCount = updates.Count(u => u.Version > _systemInformation.OrchardCoreVersion);
30 |
31 | return updatesCount == 0
32 | ? HealthCheckResult.Healthy()
33 | : HealthCheckResult.Unhealthy(S.Plural(updatesCount, "There's {0} update available.", "There're {0} updates available.", updatesCount));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "System",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.4.1",
9 | Category = "Utilities"
10 | )]
11 |
12 | [assembly: Feature(
13 | Id = "OrchardCoreContrib.System",
14 | Name = "System",
15 | Description = "Provides an information about currently running application.",
16 | DefaultTenantOnly = true
17 | )]
18 |
19 | [assembly: Feature(
20 | Id = "OrchardCoreContrib.System.Updates",
21 | Name = "System Updates",
22 | Description = "Displays the available system updates.",
23 | Dependencies = new[] { "OrchardCoreContrib.System" },
24 | DefaultTenantOnly = true
25 | )]
26 |
27 | [assembly: Feature(
28 | Id = "OrchardCoreContrib.System.Maintenance",
29 | Name = "System Maintenance",
30 | Description = "Put your site in maintenance mode while you're doing upgrades.",
31 | Dependencies = new[] { "OrchardCore.Autoroute" }
32 | )]
33 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Models/SystemUpdate.cs:
--------------------------------------------------------------------------------
1 | using NuGet.Versioning;
2 |
3 | namespace OrchardCoreContrib.System.Models;
4 |
5 | public class SystemUpdate
6 | {
7 | private readonly NuGetVersion _version;
8 |
9 | public SystemUpdate(NuGetVersion version)
10 | {
11 | _version = version;
12 | }
13 |
14 | public Version Version => _version.Version;
15 |
16 | public override string ToString() => _version.ToFullString();
17 | }
18 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Permissions.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Security.Permissions;
2 |
3 | namespace OrchardCoreContrib.System;
4 |
5 | ///
6 | /// Represents a permissions that will be applied into System module.
7 | ///
8 | public class Permissions : IPermissionProvider
9 | {
10 | ///
11 | /// Gets a permission for managing a System settings.
12 | ///
13 | public static readonly Permission ManageSystemSettings = new("ManageSystemSettings", "Manage System Settings");
14 |
15 | ///
16 | public Task> GetPermissionsAsync() => Task.FromResult(new[] { ManageSystemSettings }.AsEnumerable());
17 |
18 | ///
19 | public IEnumerable GetDefaultStereotypes() => new[]
20 | {
21 | new PermissionStereotype
22 | {
23 | Name = "Administrator",
24 | Permissions = new[] { ManageSystemSettings }
25 | },
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Services/ISystemUpdateService.cs:
--------------------------------------------------------------------------------
1 | using OrchardCoreContrib.System.Models;
2 |
3 | namespace OrchardCoreContrib.System.Services;
4 |
5 | public interface ISystemUpdateService
6 | {
7 | Task> GetUpdatesAsync();
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Services/SystemInformation.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore;
2 | using OrchardCore.Data;
3 | using OrchardCore.Environment.Shell;
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | namespace OrchardCoreContrib.System.Services;
8 |
9 | public class SystemInformation
10 | {
11 | private readonly ShellSettings _defaultShellSettings;
12 | private readonly Assembly _executedAssembly;
13 |
14 | public SystemInformation(IShellHost shellHost)
15 | {
16 | _executedAssembly = Assembly.GetEntryAssembly();
17 | _defaultShellSettings = shellHost.GetSettings(ShellSettings.DefaultShellName);
18 | }
19 |
20 | public string ApplicationName => _executedAssembly.GetName().Name;
21 |
22 | public Version ApplicationVersion => _executedAssembly.GetName().Version;
23 |
24 | public Version OrchardCoreVersion => typeof(IOrchardHelper).Assembly.GetName().Version;
25 |
26 | public string AspNetCoreVersion => RuntimeInformation.FrameworkDescription;
27 |
28 | public string OSVersion => RuntimeInformation.OSDescription;
29 |
30 | public string DatabaseProvider => _defaultShellSettings["DatabaseProvider"] switch
31 | {
32 | DatabaseProviderValue.Sqlite => "SQLite",
33 | DatabaseProviderValue.SqlConnection => "SQL Server",
34 | DatabaseProviderValue.MySql => "MySQL",
35 | DatabaseProviderValue.Postgres => "Postgres SQL",
36 | _ => "Unknown"
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/SystemMaintenanceConstants.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.System;
2 |
3 | public class SystemMaintenanceConstants
4 | {
5 | public const string MaintenancePath = "/maintenance";
6 |
7 | public const string DefaultMaintenancePageContent = @"
8 |
Under Maintenance
9 |
This website is currently offline for maintenance. Please try again later.
10 |
";
11 | }
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/SystemSettings.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.System;
2 |
3 | public class SystemSettings
4 | {
5 | public bool AllowMaintenanceMode { get; set; }
6 | }
7 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/SystemUpdatesConstants.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.System;
2 |
3 | public class SystemUpdatesConstants
4 | {
5 | public const string NugetPackageSource = "https://api.nuget.org/v3/index.json";
6 |
7 | public const string NuGetPackageUrl = "https://www.nuget.org/packages";
8 |
9 | public const string OrchardCorePackageId = "OrchardCore";
10 | }
11 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/UpdatesAdminMenu.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Localization;
2 | using OrchardCore.Navigation;
3 | using OrchardCoreContrib.Navigation;
4 |
5 | namespace OrchardCoreContrib.System;
6 |
7 | using OrchardCoreContrib.Navigation;
8 |
9 | ///
10 | /// Represents an admin menu for System Updates feature.
11 | ///
12 | public class UpdatesAdminMenu : AdminNavigationProvider
13 | {
14 | private readonly IStringLocalizer S;
15 |
16 | ///
17 | /// Initializes a new instance of .
18 | ///
19 | /// The .
20 | public UpdatesAdminMenu(IStringLocalizer stringLocalizer)
21 | {
22 | S = stringLocalizer;
23 | }
24 |
25 | ///
26 | public override void BuildNavigation(NavigationBuilder builder)
27 | {
28 | builder.Add(S["System"], "100", info => info
29 | .AddClass("system").Id("system")
30 | .Add(S["Info"], S["Info"].PrefixPosition(), updates => updates
31 | .AddClass("info").Id("info")
32 | .Action("About", "Admin", "OrchardCoreContrib.System")
33 | .LocalNav())
34 | .Add(S["Updates"], S["Updates"].PrefixPosition(), updates => updates
35 | .AddClass("updates").Id("updates")
36 | .Action("Updates", "Admin", "OrchardCoreContrib.System")
37 | .LocalNav())
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/ViewModels/AboutViewModel.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Environment.Extensions.Features;
2 | using OrchardCore.Environment.Shell;
3 | using OrchardCoreContrib.System.Services;
4 |
5 | namespace OrchardCoreContrib.System.ViewModels;
6 |
7 | public class AboutViewModel
8 | {
9 | public SystemInformation SystemInformation { get; set; }
10 |
11 | public IEnumerable Tenants { get; set; }
12 |
13 | public IEnumerable Features { get; set; }
14 | }
15 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/ViewModels/UpdatesViewModel.cs:
--------------------------------------------------------------------------------
1 | using NuGet.Versioning;
2 | using OrchardCoreContrib.System.Models;
3 | using OrchardCoreContrib.System.Services;
4 |
5 | namespace OrchardCoreContrib.System.ViewModels;
6 |
7 | public class UpdatesViewModel
8 | {
9 | public SystemInformation SystemInformation { get; set; }
10 |
11 | public IEnumerable Updates { get; set; }
12 | }
13 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Views/Admin/Updates.cshtml:
--------------------------------------------------------------------------------
1 | @using NuGet.Versioning;
2 | @using OrchardCore.Environment.Shell;
3 | @using OrchardCoreContrib.System
4 | @using OrchardCoreContrib.System.ViewModels;
5 | @using System.Reflection;
6 | @model UpdatesViewModel
7 | @{
8 | var hasUpdates = Model.Updates.Any();
9 | }
10 | @functions
11 | {
12 | public static IEnumerable OrchardCoreAssemblies => Assembly.GetEntryAssembly()
13 | .GetReferencedAssemblies()
14 | .Where(a => a.Name.StartsWith("OrchardCore") && !a.Name.StartsWith("OrchardCoreContrib"));
15 | }
16 | @RenderTitleSegments(T["System Updates"])
17 |
18 | @if (hasUpdates)
19 | {
20 |
21 | @foreach (var update in Model.Updates)
22 | {
23 |
24 | @update
25 |
26 | @foreach (var assembly in OrchardCoreAssemblies)
27 | {
28 | var packageUrl = String.Join("/", SystemUpdatesConstants.NuGetPackageUrl, assembly.Name, update);
29 | @assembly.Name
30 | }
31 |
32 |
33 | }
34 |
35 | }
36 | else
37 | {
38 |
39 |
@T["You're all up to date!"]
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Views/NavigationItemText-info.Id.cshtml:
--------------------------------------------------------------------------------
1 | @T["Info"]
2 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Views/NavigationItemText-system.Id.cshtml:
--------------------------------------------------------------------------------
1 | @T["System"]
2 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Views/NavigationItemText-updates.Id.cshtml:
--------------------------------------------------------------------------------
1 | @T["Updates"]
2 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Views/SystemSettings.Edit.cshtml:
--------------------------------------------------------------------------------
1 | @using OrchardCoreContrib.System
2 | @model SystemSettings
3 |
4 |
5 |
6 | @T["Allow maintenance mode"]
7 | @T["Check to let the maintenance page to be displayed instead of all the site pages, this is useful if you're doing an upgrade or maintenance to your website."]
8 |
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.System/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @inherits OrchardCore.DisplayManagement.Razor.RazorPage
2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
3 | @addTagHelper *, OrchardCore.DisplayManagement
4 | @addTagHelper *, OrchardCore.ResourceManagement
5 | @using OrchardCore.DisplayManagement
6 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Tenants/HealthChecks/Extensions/TenantsHealthCheckExtensions.cs:
--------------------------------------------------------------------------------
1 | using OrchardCoreContrib.Tenants.HealthChecks;
2 |
3 | namespace Microsoft.Extensions.DependencyInjection;
4 |
5 | public static class TenantsHealthCheckExtensions
6 | {
7 | public static IHealthChecksBuilder AddTenantsCheck(this IHealthChecksBuilder healthChecksBuilder)
8 | => healthChecksBuilder.AddCheck(TenantsHealthCheck.Name);
9 | }
10 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Tenants/HealthChecks/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Diagnostics.HealthChecks;
3 | using Microsoft.AspNetCore.Routing;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Options;
6 | using OrchardCore.Modules;
7 | using OrchardCoreContrib.HealthChecks;
8 |
9 | namespace OrchardCoreContrib.Tenants.HealthChecks;
10 |
11 | [RequireFeatures("OrchardCoreContrib.HealthChecks")]
12 | public class Startup : StartupBase
13 | {
14 | public override void ConfigureServices(IServiceCollection services)
15 | {
16 | services.AddHealthChecks()
17 | .AddTenantsCheck();
18 | }
19 |
20 | public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
21 | {
22 | var healthChecksOptions = serviceProvider.GetService>().Value;
23 |
24 | routes.MapHealthChecks($"{healthChecksOptions.Url}/tenants", new HealthCheckOptions
25 | {
26 | Predicate = r => r.Name == TenantsHealthCheck.Name
27 | });
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Tenants/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "Multitenancy",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.2.1",
9 | Description = "Provides a way to manage tenants from the admin.",
10 | Category = "Infrastructure",
11 | Dependencies = new [] { "OrchardCore.Tenants" },
12 | DefaultTenantOnly = true
13 | )]
14 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "generateSourceMaps": false,
4 | "generateRTL": true,
5 | "inputs": [
6 | "Assets/scss/admin.scss"
7 | ],
8 | "output": "wwwroot/css/TheAdmin.css"
9 | },
10 | {
11 | "generateSourceMaps": false,
12 | "inputs": [
13 | "node_modules/@popperjs/core/dist/umd/popper.js",
14 | "node_modules/bootstrap/dist/js/bootstrap.js",
15 | "Assets/js/*.js"
16 | ],
17 | "output": "wwwroot/js/TheAdmin.js"
18 | },
19 | {
20 | "generateSourceMaps": false,
21 | "inputs": [
22 | "Assets/js/header/userPreferencesLoader.js"
23 | ],
24 | "output": "wwwroot/js/TheAdmin-header.js"
25 | },
26 | {
27 | "generateSourceMaps": false,
28 | "inputs": [
29 | "node_modules/material-icons/iconfont/material-icons.scss"
30 | ],
31 | "output": "wwwroot/fonts/material-icons/material-icons.css"
32 | },
33 | {
34 | "copy": true,
35 | "inputs": [
36 | "node_modules/material-icons/iconfont/*.woff",
37 | "node_modules/material-icons/iconfont/*.woff2"
38 | ],
39 | "output": "wwwroot/fonts/material-icons/@"
40 | }
41 | ]
42 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/js/darkmode.js:
--------------------------------------------------------------------------------
1 | $('#btn-darkmode').click(function() {
2 | if($('html').attr('data-theme') === 'darkmode')
3 | {
4 | $('html').attr('data-theme', 'default');
5 | $(this).children(':first').removeClass('fa-sun');
6 | $(this).children(':first').addClass('fa-moon');
7 | }
8 | else
9 | {
10 | $('html').attr('data-theme', 'darkmode');
11 | $(this).children(':first').removeClass('fa-moon');
12 | $(this).children(':first').addClass('fa-sun');
13 | }
14 |
15 | persistAdminPreferences();
16 | });
17 |
18 | $(function() {
19 | if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)
20 | {
21 | if($('html').attr('data-theme') === 'darkmode')
22 | {
23 | $('#btn-darkmode').children(':first').removeClass('fa-moon');
24 | $('#btn-darkmode').children(':first').addClass('fa-sun');
25 | }
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/js/userPreferencesPersistor.js:
--------------------------------------------------------------------------------
1 | // Each time the sidebar status is modified, that is persisted to localStorage.
2 | // When the page is loaded again, userPreferencesLoader.js will read that info to
3 | // restore the sidebar to the previous state.
4 | function persistAdminPreferences() {
5 | setTimeout(function () {
6 | var tenant = $('html').attr('data-tenant');
7 | var key = tenant + '-adminPreferences';
8 | var adminPreferences = {};
9 | adminPreferences.leftSidebarCompact = $('body').hasClass('left-sidebar-compact') ? true : false;
10 | adminPreferences.isCompactExplicit = isCompactExplicit;
11 | adminPreferences.darkMode = $('html').attr('data-theme') === 'darkmode' ? true : false;
12 | localStorage.setItem(key, JSON.stringify(adminPreferences));
13 | Cookies.set(key, JSON.stringify(adminPreferences), { expires: 360 });
14 | }, 200);
15 | }
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/mixins/_cursors.scss:
--------------------------------------------------------------------------------
1 | // Used to @include a cursor within a pre-existing class
2 | @mixin cursor($cursor-type) {
3 | cursor: $cursor-type;
4 | }
5 |
6 | // Used to generate cursor classes
7 | @mixin cursor-class($cursor-type) {
8 | .cursor-#{$cursor-type} {
9 | cursor: $cursor-type;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/mixins/_grid.scss:
--------------------------------------------------------------------------------
1 | // Row / Column Groupings
2 | // Creates mixins to target columns contained inside a column grouping to expand small sizes.
3 | // ------------------------------
4 |
5 | @mixin make-col-fix($breakpoint) {
6 | .col-#{$breakpoint} {
7 | flex: 0 0 100%;
8 | max-width: 100%;
9 | }
10 | }
11 |
12 | @mixin make-col-grouping($grouping) {
13 | &.col-#{$grouping} {
14 | @each $breakpoint in map-keys($grid-breakpoints) {
15 | @include make-col-fix(#{$breakpoint});
16 | @for $i from 1 through math.div($grid-columns, 2) {
17 | @include make-col-fix(#{$breakpoint}-#{$i});
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/mixins/_word-wrap.scss:
--------------------------------------------------------------------------------
1 | @mixin word-wrap() {
2 | overflow-wrap: break-word;
3 | word-wrap: break-word;
4 | -ms-word-break: break-all;
5 | word-break: break-all;
6 | word-break: break-word;
7 | -ms-hyphens: auto;
8 | -moz-hyphens: auto;
9 | -webkit-hyphens: auto;
10 | hyphens: auto;
11 | }
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_bootstrap-select.scss:
--------------------------------------------------------------------------------
1 | // bootstrap-select customizations
2 |
3 | .multiselect__content-wrapper ul {
4 | padding-left: unset;
5 | }
6 |
7 | .bootstrap-select {
8 | .popover-header {
9 | .close {
10 | @extend .btn;
11 | @extend .btn-close;
12 | @extend .float-end;
13 | padding-top: 0px;
14 | padding-right: 0px;
15 | background: unset;
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_codemirror.scss:
--------------------------------------------------------------------------------
1 | .CodeMirror {
2 | height: auto;
3 | border: 1px solid #ddd;
4 | }
5 |
6 | .CodeMirror-fullscreen {
7 | z-index: 1000;
8 | top: 0px !important;
9 | }
10 |
11 | .CodeMirror pre {
12 | padding-left: 7px;
13 | line-height: 1.25;
14 | margin-bottom: 0;
15 | overflow: unset;
16 | }
17 |
18 | .CodeMirror-activeline-background {
19 | background: transparent !important;
20 | }
21 |
22 | .CodeMirror-focused .CodeMirror-activeline-background {
23 | background: rgba(100, 100, 100, 0.1) !important;
24 | }
25 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_grid.scss:
--------------------------------------------------------------------------------
1 | // Responsive sizes
2 | // Creates mixins to target all breakpoints
3 | // ------------------------------
4 | .col-xsmall {
5 | @extend .col-8, .col-sm-4, .col-md-3, .col-lg-2, .col-xl-1;
6 | }
7 |
8 | .col-small {
9 | @extend .col-12, .col-sm-9, .col-md-6, .col-lg-3, .col-xl-3;
10 | }
11 |
12 | .col-medium {
13 | @extend .col-12, .col-sm-12, .col-md-10, .col-lg-8, .col-xl-6;
14 | }
15 |
16 | .col-large {
17 | @extend .col-12, .col-sm-12, .col-md-12, .col-lg-12, .col-xl-9;
18 | }
19 |
20 | .col-xlarge {
21 | @extend .col-12, .col-sm-12, .col-md-12, .col-lg-12, .col-xl-12;
22 | }
23 |
24 | .ta-col-grouping {
25 | // Column fixes
26 | @each $breakpoint in map-keys($grid-breakpoints) {
27 | @if $grid-row-columns > 0 {
28 | // Column fixes
29 | @include make-col-grouping(#{$breakpoint}); // Include a fix for unspecified cols, i.e. col-md
30 | // Only apply to the lower half of the grid.
31 | @for $i from 1 through math.div($grid-columns, 2) {
32 | // Include a fix for specified cols, i.e. col-md-3
33 | @include make-col-grouping(#{$breakpoint}-#{$i});
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_jquery-ui.scss:
--------------------------------------------------------------------------------
1 | #ui-datepicker-div {
2 | z-index: 100 !important;
3 | }
4 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_list.scss:
--------------------------------------------------------------------------------
1 | .list-group li:hover {
2 | background-color: $li-hover-bg-color;
3 | }
4 |
5 | .list-group-item.first-child-visible {
6 | border-top-width: 1px !important;
7 | border-top-left-radius: inherit;
8 | border-top-right-radius: inherit;
9 | }
10 |
11 | .list-group-item.last-child-visible {
12 | border-bottom-left-radius: inherit;
13 | border-bottom-right-radius: inherit;
14 | }
15 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_login.scss:
--------------------------------------------------------------------------------
1 | .ta-content-login {
2 | margin-left: 0 !important;
3 | }
4 |
5 | .auth-form {
6 | label {
7 | display: block;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_messages.scss:
--------------------------------------------------------------------------------
1 | // Messages
2 | // ------------------------------
3 | .message {
4 | @extend .alert;
5 | }
6 |
7 | .message-success {
8 | @extend .alert-success;
9 | }
10 |
11 | .message-information {
12 | @extend .alert-info;
13 | }
14 |
15 | .message-warning {
16 | @extend .alert-warning;
17 | }
18 |
19 | .message-error {
20 | @extend .alert-danger;
21 | }
22 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_monaco.scss:
--------------------------------------------------------------------------------
1 | div.editor-widget.find-widget {
2 | .button.codicon {
3 | background-color: transparent;
4 | border-color: transparent;
5 | display: flex;
6 | color: rgb(97,97,97);
7 | box-shadow: none;
8 | }
9 |
10 | .button.codicon:focus {
11 | background-color: transparent;
12 | border-color: transparent;
13 | }
14 |
15 | .button.codicon:active {
16 | background-color: transparent;
17 | border-color: transparent;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_pager.scss:
--------------------------------------------------------------------------------
1 | // Pager ========================
2 |
3 | ul.pager {
4 | @extend .pagination;
5 | margin-top: 1rem;
6 | justify-content: center;
7 | }
8 |
9 | ul.pager li {
10 | @extend .page-item;
11 | }
12 |
13 | ul.pager li a {
14 | @extend .page-link;
15 | }
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_trumbowyg.scss:
--------------------------------------------------------------------------------
1 | .trumbowyg {
2 | font-size: 16px;
3 | }
4 |
5 | .trumbowyg-fullscreen {
6 | z-index: 1040;
7 | }
8 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/admin/_validations.scss:
--------------------------------------------------------------------------------
1 | .field-validation-error, .has-validation-error {
2 | @extend .text-danger;
3 | }
4 |
5 | span.field-validation-error {
6 | width: 100%;
7 | }
8 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/theme/darkmode/_admin-variables.scss:
--------------------------------------------------------------------------------
1 | // You can override any bootstrap or module variables here.
2 |
3 | $top-nav-height: 52px;
4 | $footer-height: 40px;
5 | $left-navigation-width: 260px;
6 | $left-navigation-width-when-compact: 48px;
7 | $border-content: 1px solid rgb(57, 62, 64);
8 | $link-padding-left: 16px !default;
9 | $zindex-sticky: 1000;
10 | $admin-menu-bg-color: rgb(36, 39, 40);
11 | $admin-menu-font-color: rgb(181, 175, 166);
12 | $admin-menu-font-color-hover: rgb(181, 175, 166);
13 | $admin-menu-item-bg-color: rgb(27, 30, 31);
14 | $admin-menu-item-font-color: rgb(189, 183, 175);
15 | $admin-menu-item-font-color-active: rgba(232, 230, 227, 0.9);
16 | $li-hover-bg-color: rgb(27, 30, 31);
17 | $scrollbar-color: #495057;
18 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/theme/darkmode/_forms.scss:
--------------------------------------------------------------------------------
1 |
2 | .has-filter .btn:not(.show) {
3 | border-color: #3C4144 !important;
4 | }
5 |
6 | .has-filter .form-control-feedback, .has-search .form-control-feedback {
7 | color: #aaa;
8 | }
9 |
10 | .has-filter .form-control, .has-search .form-control {
11 | color: #aaa;
12 | }
13 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/theme/default/_admin-variables.scss:
--------------------------------------------------------------------------------
1 | // You can override any bootstrap or module variables here.
2 |
3 | $top-nav-height: 52px;
4 | $footer-height: 40px;
5 | $left-navigation-width: 260px;
6 | $left-navigation-width-when-compact: 48px;
7 | $border-content: 1px solid #dedede;
8 | $link-padding-left: 16px !default;
9 | $zindex-sticky: 1000;
10 | $admin-menu-bg-color: #eaeaea;
11 | $admin-menu-font-color: $gray-800;
12 | $admin-menu-font-color-hover: $gray-100;
13 | $admin-menu-item-bg-color: $gray-100;
14 | $admin-menu-item-font-color: $gray-700;
15 | $admin-menu-item-font-color-active: black;
16 | $li-hover-bg-color: $gray-100;
17 | $scrollbar-color: #495057;
18 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/theme/default/_forms.scss:
--------------------------------------------------------------------------------
1 | .has-filter .btn:not(.show) {
2 | border-color: $gray-400 !important;
3 | }
4 |
5 | .has-filter .form-control-feedback, .has-search .form-control-feedback {
6 | color: #aaa;
7 | }
8 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Assets/scss/modules/theme/default/_variables.scss:
--------------------------------------------------------------------------------
1 | // Override Bootstrap variables
2 | // Because !default means that a variable is not assigned if it already contains a value,
3 | // we alter the variable before importing boostrap as _variables.scss will use !default
4 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.DisplayManagement.Manifest;
2 | using OrchardCore.Modules.Manifest;
3 |
4 | [assembly: Theme(
5 | Name = "Orchard Core Contrib Admin Theme",
6 | Author = "Orchard Core Contrib",
7 | Version = "1.0.0",
8 | Description = "The default Admin theme.",
9 | Tags = new[] { ManifestConstants.AdminTag }
10 | )]
11 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/OrchardCoreContrib.Themes.Admin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Options;
3 | using OrchardCore.DisplayManagement.Html;
4 | using OrchardCore.Environment.Shell.Configuration;
5 | using OrchardCore.Modules;
6 | using OrchardCore.ResourceManagement;
7 |
8 | namespace OrchardCoreContrib.Themes.Admin
9 | {
10 | public class Startup : StartupBase
11 | {
12 | private readonly IShellConfiguration _configuration;
13 |
14 | public Startup(IShellConfiguration configuration)
15 | {
16 | _configuration = configuration;
17 | }
18 |
19 | public override void ConfigureServices(IServiceCollection services)
20 | {
21 | // TODO: Check why the resources broken after upgrading to Orchard Core 1.8.2
22 | //services.AddTransient, ResourceManagementOptionsConfiguration>();
23 | //services.Configure(_configuration.GetSection("TheAdminTheme:StyleSettings"));
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Views/Message.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | string type = Model.Type.ToString().ToLowerInvariant();
3 | }
4 |
5 | @Model.Message
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Views/NavigationItemText.cshtml:
--------------------------------------------------------------------------------
1 | @using System.Linq
2 |
3 | @{
4 |
5 | var prefix = "icon-class-";
6 |
7 | //extract icon classes from Model.Classes
8 | var iconClasses = ((IEnumerable)Model.Classes)
9 | .ToList()
10 | .Where(c => c.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
11 | .Select(c => c.Substring(prefix.Length));
12 |
13 | if (iconClasses.Any())
14 | {
15 |
16 | }
17 | else
18 | {
19 | @* *@
20 | }
21 |
22 | }
23 | @Model.Text
24 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @*
2 | For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
3 |
4 | *@
5 |
6 | @inherits OrchardCore.DisplayManagement.Razor.RazorPage
7 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
8 | @addTagHelper *, OrchardCore.DisplayManagement
9 | @addTagHelper *, OrchardCore.ResourceManagement
10 |
11 | @using Microsoft.Extensions.Options
12 | @using OrchardCore.Admin
13 | @using OrchardCore.Admin.Models
14 | @using OrchardCore.Entities
15 | @using OrchardCore.Themes.Services
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "orchardcore.theadmin",
3 | "version": "1.0.0",
4 | "dependencies": {
5 | "@popperjs/core": "2.11.5",
6 | "bootstrap": "5.1.3",
7 | "bootstrap-select": "1.14.0-beta2",
8 | "material-icons": "1.12.0",
9 | "nouislider": "15.6.1"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/Theme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/Theme.png
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-outlined.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-outlined.woff
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-outlined.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-outlined.woff2
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-round.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-round.woff
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-round.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-round.woff2
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-sharp.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-sharp.woff
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-sharp.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-sharp.woff2
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-two-tone.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-two-tone.woff
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-two-tone.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons-two-tone.woff2
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons.woff
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OrchardCoreContrib/OrchardCoreContrib.Modules/3a124143f9e750c2d34535492c353f555dbe1d4b/src/OrchardCoreContrib.Themes.Admin/wwwroot/fonts/material-icons/material-icons.woff2
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Themes.Admin/wwwroot/js/TheAdmin-header.min.js:
--------------------------------------------------------------------------------
1 | var observer=new MutationObserver((function(e){for(var t=document.querySelector("html"),a=t.getAttribute("data-tenant")+"-adminPreferences",d=JSON.parse(localStorage.getItem(a)),r=0;r S) : AdminNavigationProvider
11 | {
12 | public override void BuildNavigation(NavigationBuilder builder)
13 | {
14 | builder
15 | .Add(S["Security"], NavigationConstants.AdminMenuConfigurationPosition, builder => builder
16 | .Add(S["User Groups"], S["User Groups"].PrefixPosition(), builder => builder
17 | .Id("usergroups")
18 | .Action(nameof(AdminController.Index), typeof(AdminController).ControllerName(), "OrchardCoreContrib.UserGroups")
19 | .LocalNav()));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Drivers/UserGroupsDisplayDriver.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.DisplayManagement.Handlers;
2 | using OrchardCore.DisplayManagement.Views;
3 | using OrchardCore.Users.Models;
4 | using OrchardCoreContrib.UserGroups.Services;
5 | using OrchardCoreContrib.UserGroups.ViewModels;
6 |
7 | namespace OrchardCoreContrib.UserGroups.Drivers;
8 |
9 | public class UserGroupsDisplayDriver(UserGroupsManager userGroupsManager) : DisplayDriver
10 | {
11 | public override IDisplayResult Display(User user, BuildDisplayContext context)
12 | => Initialize("UserGroups", model => model.UserGroups = user.GetUserGroups())
13 | .Location("DetailAdmin", "Content:10");
14 |
15 | public async override Task EditAsync(User user, BuildEditorContext context)
16 | {
17 | var userGroupNames = await userGroupsManager.GetUserGroupNamesAsync();
18 |
19 | return Initialize("UserGroups_Edit", model =>
20 | {
21 | model.UserGroups = userGroupNames;
22 | model.SelectedUserGroups = user.GetUserGroups();
23 | }).Location("Content:10");
24 | }
25 |
26 | public async override Task UpdateAsync(User user, UpdateEditorContext context)
27 | {
28 | var model = new UserGroupsEditViewModel();
29 |
30 | await context.Updater.TryUpdateModelAsync(model, Prefix);
31 |
32 | user.SetUserGroups(model.SelectedUserGroups);
33 |
34 | return Edit(user, context);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Extensions/UserExtensions.cs:
--------------------------------------------------------------------------------
1 | using OrchardCoreContrib.Infrastructure;
2 | using System.Text.Json.Nodes;
3 |
4 | namespace OrchardCore.Users.Models;
5 |
6 | internal static class UserExtensions
7 | {
8 | private const string UserGroupsPropertyName = "UserGroups";
9 |
10 | public static string[] GetUserGroups(this User user)
11 | {
12 | Guard.ArgumentNotNull(user, nameof(user));
13 |
14 | return user.Properties.TryGetPropertyValue(UserGroupsPropertyName, out var userGroupsJson)
15 | ? userGroupsJson.ToObject()
16 | : [];
17 | }
18 |
19 | public static void SetUserGroups(this User user, string[] groups)
20 | {
21 | Guard.ArgumentNotNull(user, nameof(user));
22 | Guard.ArgumentNotNull(groups, nameof(groups));
23 |
24 | user.Properties[UserGroupsPropertyName] = JNode.FromObject(groups);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Indexes/UserByGroupNameIndex.cs:
--------------------------------------------------------------------------------
1 | using YesSql.Indexes;
2 |
3 | namespace OrchardCoreContrib.UserGroups.Indexes;
4 |
5 | public class UserByGroupNameIndex : ReduceIndex
6 | {
7 | public string GroupName { get; set; }
8 |
9 | public int Count { get; set; }
10 | }
11 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Indexes/UserByUserGroupNameIndexProvider.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Identity;
2 | using OrchardCore.Users.Models;
3 | using YesSql.Indexes;
4 |
5 | namespace OrchardCoreContrib.UserGroups.Indexes;
6 |
7 | public class UserByUserGroupNameIndexProvider(ILookupNormalizer keyNormalizer) : IndexProvider
8 | {
9 | public override void Describe(DescribeContext context)
10 | {
11 | context.For()
12 | .Map(user => user.GetUserGroups().Select(group => new UserByGroupNameIndex
13 | {
14 | GroupName = keyNormalizer.NormalizeName(group),
15 | Count = 1
16 | }))
17 | .Group(index => index.GroupName)
18 | .Reduce(group => new UserByGroupNameIndex
19 | {
20 | GroupName = group.Key,
21 | Count = group.Sum(x => x.Count)
22 | })
23 | .Delete((index, map) =>
24 | {
25 | index.Count -= map.Sum(x => x.Count);
26 |
27 | return index.Count > 0
28 | ? index
29 | : null;
30 | });
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "User Groups",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.0.0",
9 | Description = "Provides a way to organize the users into group(s).",
10 | Category = "Security"
11 | )]
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Migrations.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.ContentManagement.Metadata;
2 | using OrchardCore.ContentManagement.Metadata.Settings;
3 | using OrchardCore.Data.Migration;
4 | using OrchardCoreContrib.UserGroups.Indexes;
5 | using YesSql.Sql;
6 |
7 | namespace OrchardCoreContrib.UserGroups;
8 |
9 | public class Migrations(IContentDefinitionManager contentDefinitionManager) : DataMigration
10 | {
11 | public async Task CreateAsync()
12 | {
13 | await contentDefinitionManager.AlterPartDefinitionAsync("UserGroupsListPart", builder => builder
14 | .Attachable()
15 | .WithDescription("Provides a way to add user group(s) for your content item."));
16 |
17 | await SchemaBuilder.CreateReduceIndexTableAsync(table => table
18 | .Column("GroupName")
19 | .Column("Count"));
20 |
21 | await SchemaBuilder.AlterIndexTableAsync(table => table
22 | .CreateIndex("IDX_UserByGroupNameIndex_GroupName", "GroupName"));
23 |
24 | return 1;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Models/UserGroup.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.UserGroups.Models;
2 |
3 | public class UserGroup
4 | {
5 | public string Name { get; set; }
6 |
7 | public string Description { get; set; }
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Models/UserGroupDocument.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Data.Documents;
2 |
3 | namespace OrchardCoreContrib.UserGroups.Models;
4 |
5 | public class UserGroupDocument : Document
6 | {
7 | public Dictionary UserGroups { get; init; } = new(StringComparer.OrdinalIgnoreCase);
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Models/UserGroupsListPart.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.ContentManagement;
2 |
3 | namespace OrchardCoreContrib.UserGroups.Models;
4 |
5 | public class UserGroupsListPart : ContentPart
6 | {
7 | public string[] UserGroups { get; set; } = [];
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Permissions.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Security.Permissions;
2 | using OrchardCore;
3 |
4 | namespace OrchardCoreContrib.UserGroups;
5 |
6 | public sealed class Permissions : IPermissionProvider
7 | {
8 | private readonly IEnumerable _permissions = [UserGroupsPermissions.ManageUserGroups];
9 |
10 | public Task> GetPermissionsAsync() => Task.FromResult(_permissions);
11 |
12 | public IEnumerable GetDefaultStereotypes() =>
13 | [
14 | new PermissionStereotype
15 | {
16 | Name = OrchardCoreConstants.Roles.Administrator,
17 | Permissions = _permissions,
18 | },
19 | ];
20 | }
21 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using OrchardCore.ContentManagement;
3 | using OrchardCore.ContentManagement.Display.ContentDisplay;
4 | using OrchardCore.Data;
5 | using OrchardCore.Data.Migration;
6 | using OrchardCore.DisplayManagement.Handlers;
7 | using OrchardCore.Modules;
8 | using OrchardCore.Navigation;
9 | using OrchardCore.Security.Permissions;
10 | using OrchardCore.Users.Models;
11 | using OrchardCoreContrib.UserGroups.Drivers;
12 | using OrchardCoreContrib.UserGroups.Indexes;
13 | using OrchardCoreContrib.UserGroups.Models;
14 | using OrchardCoreContrib.UserGroups.Services;
15 |
16 | namespace OrchardCoreContrib.UserGroups;
17 |
18 | public sealed class Startup : StartupBase
19 | {
20 | public override void ConfigureServices(IServiceCollection services)
21 | {
22 | services.AddIndexProvider();
23 |
24 | services.AddDataMigration();
25 | services.AddPermissionProvider();
26 | services.AddNavigationProvider();
27 |
28 | services.AddContentPart()
29 | .UseDisplayDriver();
30 |
31 | services.AddScoped, UserGroupsDisplayDriver>();
32 | services.AddScoped();
33 | services.AddScoped();
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/UserGroupsPermissions.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Security.Permissions;
2 |
3 | namespace OrchardCoreContrib.UserGroups;
4 |
5 | public static class UserGroupsPermissions
6 | {
7 | public static readonly Permission ManageUserGroups = new("ManageUserGroups", "Managing User Groups");
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/ViewModels/CreateUserGroupViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace OrchardCoreContrib.UserGroups.ViewModels;
4 |
5 | public class CreateUserGroupViewModel
6 | {
7 | [Required]
8 | public string Name { get; set; }
9 |
10 | public string Description { get; set; }
11 | }
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/ViewModels/EditUserGroupViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.UserGroups.ViewModels;
2 |
3 | public class EditUserGroupViewModel
4 | {
5 | public string Name { get; set; }
6 |
7 | public string Description { get; set; }
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/ViewModels/UserGroupsEditViewModel.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc.ModelBinding;
2 |
3 | namespace OrchardCoreContrib.UserGroups.ViewModels;
4 |
5 | public class UserGroupsEditViewModel
6 | {
7 | [BindNever]
8 | public IEnumerable UserGroups { get; set; }
9 |
10 | public string[] SelectedUserGroups { get; set; }
11 | }
12 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/ViewModels/UserGroupsIndexViewModel.cs:
--------------------------------------------------------------------------------
1 | using OrchardCoreContrib.UserGroups.Models;
2 |
3 | namespace OrchardCoreContrib.UserGroups.ViewModels;
4 |
5 | public class UserGroupsIndexViewModel
6 | {
7 | public IEnumerable UserGroups { get; set; } = [];
8 |
9 | public string Search { get; set; }
10 |
11 | public dynamic Pager { get; set; }
12 | }
13 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/ViewModels/UserGroupsListPartEditViewModel.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc.ModelBinding;
2 | namespace OrchardCoreContrib.UserGroups.ViewModels;
3 |
4 | public class UserGroupsListPartEditViewModel
5 | {
6 | [BindNever]
7 | public IEnumerable UserGroups { get; set; }
8 |
9 | public string[] SelectedUserGroups { get; set; }
10 | }
11 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/ViewModels/UserGroupsListPartViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.UserGroups.ViewModels;
2 |
3 | public class UserGroupsListPartViewModel
4 | {
5 | public string[] UserGroups { get; set; }
6 | }
7 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/ViewModels/UserGroupsViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.UserGroups.ViewModels;
2 |
3 | public class UserGroupsViewModel
4 | {
5 | public string[] UserGroups { get; set; }
6 | }
7 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Views/Admin/Create.cshtml:
--------------------------------------------------------------------------------
1 | @model CreateUserGroupViewModel
2 |
3 | @RenderTitleSegments(T["Create User Group"])
4 |
5 |
6 |
7 |
8 |
9 | @T["Name"]
10 |
11 |
12 |
13 |
14 | @T["Description"]
15 |
16 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Views/Admin/Edit.cshtml:
--------------------------------------------------------------------------------
1 | @model EditUserGroupViewModel
2 |
3 | @RenderTitleSegments(T["Edit '{0}' User Group", Model.Name])
4 |
5 |
6 |
7 | @T["Description"]
8 |
9 |
10 |
11 |
15 |
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Views/NavigationItemText-usergroups.Id.cshtml:
--------------------------------------------------------------------------------
1 | @T["User Groups"]
2 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Views/UserGroups.Edit.cshtml:
--------------------------------------------------------------------------------
1 | @model UserGroupsEditViewModel
2 |
3 | @T["User Groups"]
4 |
5 | @foreach (var userGroup in Model.UserGroups)
6 | {
7 | var selected = Model.SelectedUserGroups.Contains(userGroup);
8 |
9 |
10 |
11 | @userGroup
12 |
13 |
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Views/UserGroups.cshtml:
--------------------------------------------------------------------------------
1 | @model UserGroupsViewModel
2 |
3 | @T["User Groups"]
4 |
5 | @foreach (var userGroup in Model.UserGroups)
6 | {
7 | @userGroup
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Views/UserGroupsListPart.Edit.cshtml:
--------------------------------------------------------------------------------
1 | @model UserGroupsListPartEditViewModel
2 |
3 | @T["User Groups"]
4 |
5 | @foreach (var userGroup in Model.UserGroups)
6 | {
7 | var selected = Model.SelectedUserGroups.Contains(userGroup);
8 |
9 |
10 |
11 | @userGroup
12 |
13 |
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Views/UserGroupsListPart.cshtml:
--------------------------------------------------------------------------------
1 | @model UserGroupsListPartViewModel
2 |
3 |
4 | @foreach (var userGroup in Model.UserGroups)
5 | {
6 | @userGroup
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.UserGroups/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @inherits OrchardCore.DisplayManagement.Razor.RazorPage
2 |
3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
4 | @addTagHelper *, OrchardCore.DisplayManagement
5 | @addTagHelper *, OrchardCore.ResourceManagement
6 |
7 | @using Microsoft.AspNetCore.Mvc.Localization
8 | @using OrchardCoreContrib.UserGroups.ViewModels
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/AvatarOptions.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.Users;
2 |
3 | public class AvatarOptions
4 | {
5 | public string BackColor { get; set; } = "#55B670";
6 |
7 | public string ForeColor { get; set; } = "#FFF";
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/ClaimTypesExtended.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.Users
2 | {
3 | ///
4 | /// Represents a claim types that be used for impersonation process.
5 | ///
6 | public static class ClaimTypesExtended
7 | {
8 | ///
9 | /// Gets the impersonator name.
10 | ///
11 | public static readonly string ImpersonatorNameIdentifier = nameof(ImpersonatorNameIdentifier);
12 |
13 | ///
14 | /// Gets whether the current user is impersonated or not.
15 | ///
16 | public static readonly string IsImpersonating = nameof(IsImpersonating);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/Drivers/ImpersonationDisplayDriver.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.DisplayManagement.Handlers;
2 | using OrchardCore.DisplayManagement.Views;
3 | using OrchardCore.Modules;
4 | using OrchardCore.Users.Models;
5 | using OrchardCore.Users.ViewModels;
6 |
7 | namespace OrchardCoreContrib.Users.Drivers;
8 |
9 | [Feature("OrchardCoreContrib.Users.Impersonation")]
10 | public class ImpersonationDisplayDriver : DisplayDriver
11 | {
12 | public override IDisplayResult Display(User user, BuildDisplayContext context)
13 | => Initialize("ImpersonationButton", model => model.User = user)
14 | .Location("SummaryAdmin", "Actions:2");
15 | }
16 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "Users",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.5.1",
9 | Category = "Security"
10 | )]
11 |
12 | [assembly: Feature(
13 | Id = "OrchardCoreContrib.Users.Avatar",
14 | Name = "User Avatar",
15 | Description = "This feature allow to display a user avatar on the admin menu.",
16 | Dependencies = new[] { "OrchardCore.Users" }
17 | )]
18 |
19 | [assembly: Feature(
20 | Id = "OrchardCoreContrib.Users.Impersonation",
21 | Name = "Users Impersonation",
22 | Description = "This feature allow administrators to sign in with other user identity.",
23 | Dependencies = new[] { "OrchardCore.Users" }
24 | )]
25 |
26 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/Permissions.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules;
2 | using OrchardCore.Security;
3 | using OrchardCore.Security.Permissions;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 |
8 | namespace OrchardCoreContrib.Users
9 | {
10 | ///
11 | /// Represents a permissions that will be applied into users module.
12 | ///
13 | [Feature("OrchardCoreContrib.Users.Impersonation")]
14 | public class Permissions : IPermissionProvider
15 | {
16 | ///
17 | /// Gets a permission for managing a impersonation settings.
18 | ///
19 | public static readonly Permission ManageImpersonationSettings = new Permission("ManageImpersonationSettings", "Manage Impersonation Settings", isSecurityCritical: true);
20 |
21 | ///
22 | public Task> GetPermissionsAsync()
23 | {
24 | return Task.FromResult(new[]
25 | {
26 | ManageImpersonationSettings
27 | }
28 | .AsEnumerable());
29 | }
30 |
31 | ///
32 | public IEnumerable GetDefaultStereotypes()
33 | {
34 | return new[]
35 | {
36 | new PermissionStereotype
37 | {
38 | Name = "Administrator",
39 | Permissions = new[] { ManageImpersonationSettings, StandardPermissions.SiteOwner }
40 | },
41 | };
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/Services/IAvatarService.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.Users.Services;
2 |
3 | public interface IAvatarService
4 | {
5 | string Generate(string userName);
6 | }
7 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/Services/NullAvatarService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace OrchardCoreContrib.Users.Services;
4 |
5 | public class NullAvatarService : IAvatarService
6 | {
7 | public string Generate(string userName) => String.Empty;
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/Views/ImpersonationButton.cshtml:
--------------------------------------------------------------------------------
1 | @using OrchardCore.Modules
2 | @using OrchardCore.Users.Models
3 | @using OrchardCore.Users.ViewModels
4 | @model SummaryAdminUserViewModel
5 | @attribute [Feature("OrchardCoreContrib.Users.Impersonation")]
6 | @{
7 | var user = Model.User as User;
8 | }
9 |
10 | @T["Impersonate"]
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/Views/NavigationItemText-endImpersonation.Id.cshtml:
--------------------------------------------------------------------------------
1 | @T["End Impersonation"]
2 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.Users/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @inherits OrchardCore.DisplayManagement.Razor.RazorPage
2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
3 | @addTagHelper *, OrchardCore.DisplayManagement
4 | @addTagHelper *, OrchardCore.ResourceManagement
5 |
6 | @using Microsoft.Extensions.Localization;
7 | @using Microsoft.AspNetCore.Mvc.Localization;
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Drivers/ViewCountPartDisplayDriver.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.ContentManagement.Display.ContentDisplay;
2 | using OrchardCore.ContentManagement.Display.Models;
3 | using OrchardCore.DisplayManagement.Views;
4 | using OrchardCoreContrib.ViewCount.Models;
5 | using OrchardCoreContrib.ViewCount.Services;
6 | using OrchardCoreContrib.ViewCount.ViewModels;
7 |
8 | namespace OrchardCoreContrib.ViewCount.Drivers;
9 |
10 | public sealed class ViewCountPartDisplayDriver(IViewCountService viewCountService) : ContentPartDisplayDriver
11 | {
12 | public async override Task DisplayAsync(ViewCountPart part, BuildPartDisplayContext context)
13 | {
14 | if (context.DisplayType == "Detail")
15 | {
16 | await viewCountService.ViewAsync(part.ContentItem);
17 | }
18 |
19 | return Initialize(GetDisplayShapeType(context), model => model.Count = part.Count)
20 | .Location("Detail", "Content:10");
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Handlers/IViewCountContentHandler.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.ViewCount.Handlers;
2 |
3 | public interface IViewCountContentHandler
4 | {
5 | Task ViewingAsync(ViewCountContentContext context);
6 |
7 | Task ViewedAsync(ViewCountContentContext context);
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Handlers/ViewCountContentContext.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.ContentManagement.Handlers;
2 | using OrchardCore.ContentManagement;
3 |
4 | namespace OrchardCoreContrib.ViewCount.Handlers;
5 |
6 | public class ViewCountContentContext(ContentItem contentItem, int count) : ContentContextBase(contentItem)
7 | {
8 | public int Count { get; set; } = count;
9 | }
10 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Handlers/ViewCountContentHandlerBase.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.ViewCount.Handlers;
2 |
3 | public abstract class ViewCountContentHandlerBase : IViewCountContentHandler
4 | {
5 | public virtual Task ViewingAsync(ViewCountContentContext context) => Task.CompletedTask;
6 |
7 | public virtual Task ViewedAsync(ViewCountContentContext context) => Task.CompletedTask;
8 | }
9 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Manifest.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.Modules.Manifest;
2 | using ManifestConstants = OrchardCoreContrib.Modules.Manifest.ManifestConstants;
3 |
4 | [assembly: Module(
5 | Name = "View Count",
6 | Author = ManifestConstants.Author,
7 | Website = ManifestConstants.Website,
8 | Version = "1.0.0",
9 | Description = "Allows to count the content item views.",
10 | Dependencies = ["OrchardCore.Contents"],
11 | Category = "Content Management"
12 | )]
13 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Migrations.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.ContentManagement.Metadata;
2 | using OrchardCore.ContentManagement.Metadata.Settings;
3 | using OrchardCore.Data.Migration;
4 |
5 | namespace OrchardCoreContrib.ViewCount;
6 |
7 | public class Migrations(IContentDefinitionManager contentDefinitionManager) : DataMigration
8 | {
9 | public async Task CreateAsync()
10 | {
11 | await contentDefinitionManager.AlterPartDefinitionAsync("ViewCountPart", builder => builder
12 | .Attachable()
13 | .WithDescription("Enables counting of views for the content item."));
14 | return 1;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Models/ViewCountPart.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.ContentManagement;
2 |
3 | namespace OrchardCoreContrib.ViewCount.Models;
4 | public class ViewCountPart : ContentPart
5 | {
6 | public int Count { get; set; }
7 | }
8 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Services/IViewCountService.cs:
--------------------------------------------------------------------------------
1 | using OrchardCore.ContentManagement;
2 |
3 | namespace OrchardCoreContrib.ViewCount.Services;
4 |
5 | public interface IViewCountService
6 | {
7 | int GetViewsCount(ContentItem contentItem);
8 |
9 | Task ViewAsync(ContentItem contentItem);
10 | }
11 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using OrchardCore.ContentManagement;
3 | using OrchardCore.ContentManagement.Display.ContentDisplay;
4 | using OrchardCore.Data.Migration;
5 | using OrchardCore.Modules;
6 | using OrchardCoreContrib.ViewCount.Drivers;
7 | using OrchardCoreContrib.ViewCount.Models;
8 | using OrchardCoreContrib.ViewCount.Services;
9 |
10 | namespace OrchardCoreContrib.ViewCount;
11 |
12 | public sealed class Startup : StartupBase
13 | {
14 | public override void ConfigureServices(IServiceCollection services)
15 | {
16 | services.AddContentPart()
17 | .UseDisplayDriver();
18 |
19 | services.AddDataMigration();
20 | services.AddScoped();
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/ViewModels/ViewCountPartViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace OrchardCoreContrib.ViewCount.ViewModels;
2 |
3 | public class ViewCountPartViewModel
4 | {
5 | public int Count { get; set; }
6 | }
7 |
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Views/ViewCountPart.cshtml:
--------------------------------------------------------------------------------
1 | @using Microsoft.AspNetCore.Mvc.Localization
2 | @model ViewCountPartViewModel
3 |
4 | @T.Plural(Model.Count, "1 view", "{0} views")
--------------------------------------------------------------------------------
/src/OrchardCoreContrib.ViewCount/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 |
2 | @inherits OrchardCore.DisplayManagement.Razor.RazorPage
3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
4 | @addTagHelper *, OrchardCore.DisplayManagement
5 | @addTagHelper *, OrchardCore.ResourceManagement
6 | @using OrchardCoreContrib.ViewCount.ViewModels
7 |
--------------------------------------------------------------------------------
/test/OrchardCoreContrib.ContentPermissions.Tests/OrchardCoreContrib.ContentPermissions.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
7 |
8 |
9 | all
10 | runtime; build; native; contentfiles; analyzers; buildtransitive
11 |
12 |
13 |
14 |
15 |
16 |
17 | all
18 | runtime; build; native; contentfiles; analyzers; buildtransitive
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/test/OrchardCoreContrib.Garnet.Tests/OrchardCoreContrib.Garnet.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
7 |
8 |
9 | all
10 | runtime; build; native; contentfiles; analyzers; buildtransitive
11 |
12 |
13 |
14 |
15 |
16 |
17 | all
18 | runtime; build; native; contentfiles; analyzers; buildtransitive
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/test/OrchardCoreContrib.Garnet.Tests/TestBase.cs:
--------------------------------------------------------------------------------
1 | using Garnet;
2 |
3 | namespace OrchardCoreContrib.Garnet.Tests;
4 |
5 | public abstract class TestBase : IAsyncLifetime
6 | {
7 | private static readonly GarnetServer _garnetServer;
8 |
9 | static TestBase()
10 | {
11 | _garnetServer = new([]);
12 | _garnetServer.Start();
13 | }
14 |
15 | public virtual async Task InitializeAsync() => await Task.CompletedTask;
16 |
17 | public virtual async Task DisposeAsync() => await Task.CompletedTask;
18 | }
19 |
--------------------------------------------------------------------------------
/test/OrchardCoreContrib.Garnet.Tests/Utilities.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Hosting;
2 | using Microsoft.Extensions.Logging;
3 | using Microsoft.Extensions.Options;
4 | using Moq;
5 | using OrchardCoreContrib.Garnet.Services;
6 |
7 | namespace OrchardCoreContrib.Garnet.Tests;
8 |
9 | public static class Utilities
10 | {
11 | public static async Task CreateGarnetServiceAsync()
12 | {
13 | var garnetClientFactory = new GarnetClientFactory(
14 | Mock.Of(),
15 | Mock.Of>());
16 | var garnetService = new GarnetService(garnetClientFactory, Options.Create(new GarnetOptions()));
17 |
18 | await garnetService.ConnectAsync();
19 |
20 | return garnetService;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/test/OrchardCoreContrib.Modules.Tests/ContentLocalization/TransliterationServiceTests.cs:
--------------------------------------------------------------------------------
1 | using OrchardCoreContrib.ContentLocalization.Services;
2 | using OrchardCoreContrib.ContentLocalization.Transliteration;
3 | using Xunit;
4 |
5 | namespace OrchardCoreContrib.Modules.ContentLocalization.Tests;
6 |
7 | public class TransliterationServiceTests
8 | {
9 | [Theory]
10 | [InlineData(TransliterateScript.Arabic, "ضروري", "drwry")]
11 | [InlineData(TransliterateScript.Arabic, "الوثائق والشهادات", "alwtha'eq walshhadat")]
12 | [InlineData(TransliterateScript.Cyrillic, "НЕОПХОДНИ", "NEOPHODNI")]
13 | [InlineData(TransliterateScript.Cyrillic, "Документа и уверења", "Dokumenta i uvereњa")]
14 | public void TransliterateText(TransliterateScript script, string text, string expectedTransliteratedText)
15 | {
16 | // Arrange
17 | var transliterationService = new TransliterationService(new DefaultTransliterateRuleProvider());
18 |
19 | // Act
20 | var transliteratedText = transliterationService.Transliterate(script, text);
21 |
22 | // Assert
23 | Assert.Equal(expectedTransliteratedText, transliteratedText);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/test/OrchardCoreContrib.Modules.Tests/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Email": {
3 | "From": "",
4 | "To": "",
5 | "Gmail": {
6 | "Username": "",
7 | "Password": ""
8 | },
9 | "Hotmail": {
10 | "Username": "",
11 | "Password": ""
12 | },
13 | "SendGrid": {
14 | "ApiKey": ""
15 | },
16 | "Yahoo": {
17 | "Username": "",
18 | "Password": ""
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/OrchardCoreContrib.UserGroups.Tests/Extensions/UserGroupsManagerExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | using Moq;
2 | using OrchardCore.Documents;
3 | using OrchardCoreContrib.UserGroups.Helpers.Tests;
4 | using OrchardCoreContrib.UserGroups.Models;
5 | using OrchardCoreContrib.UserGroups.Services;
6 |
7 | namespace OrchardCoreContrib.UserGroups.Extensions.Tests;
8 |
9 | public class UserGroupsManagerExtensionsTests
10 | {
11 | [Fact]
12 | public async Task GetUserGroupNamesAsync_ShouldReturnUserGroupNames()
13 | {
14 | // Arrange
15 | var userGroup1 = new UserGroup { Name = "Group1" };
16 | var userGroup2 = new UserGroup { Name = "Group2" };
17 | var (userGroupsManager, _) = UserGroupsManagerHelper.Create(userGroup1, userGroup2);
18 |
19 | // Act
20 | var result = await userGroupsManager.GetUserGroupNamesAsync();
21 |
22 | // Assert
23 | Assert.Equal([userGroup1.Name, userGroup2.Name], result);
24 | }
25 |
26 | [Fact]
27 | public async Task CreateAsync_ShouldCreatesUserGroup()
28 | {
29 | // Arrange
30 | var groupName = "TestGroup";
31 | var (userGroupsManager, documentManager) = UserGroupsManagerHelper.Create();
32 |
33 | // Act
34 | var result = await userGroupsManager.CreateAsync(groupName, string.Empty);
35 |
36 | // Assert
37 | Assert.True(result.Succeeded);
38 |
39 | var userGroupDocument = await documentManager.GetOrCreateImmutableAsync();
40 | Assert.NotEmpty(userGroupDocument.UserGroups);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/test/OrchardCoreContrib.UserGroups.Tests/OrchardCoreContrib.UserGroups.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
7 |
8 |
9 | all
10 | runtime; build; native; contentfiles; analyzers; buildtransitive
11 |
12 |
13 |
14 |
15 |
16 |
17 | all
18 | runtime; build; native; contentfiles; analyzers; buildtransitive
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------