Git Product home page Git Product logo

oqtane.framework's People

Contributors

adefwebserver avatar alikoli avatar behnam-emamian avatar cnurse avatar fileman avatar gjwalk avatar hishamco avatar hoenesdk avatar ijungleboy avatar isaeed avatar jayson-furr avatar jimspillane avatar leigh-pointer avatar marcdrexel avatar markdav-is avatar mdmontesinos avatar mikecasas avatar mitchelsellers avatar ohba-ikuo avatar pavelvsl avatar pizzaconsole avatar pyramidsbuilder avatar sbwalker avatar spseanlong avatar svreic avatar thabaum avatar tvatavuk avatar vnetonline avatar w6hbr avatar zyhfish avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oqtane.framework's Issues

Bug: Deleting a Page: The input does not contain any JSON tokens

To reproduce:

  1. As the Host, create a new page
  2. Try to delete the page

You will get the following error:

System.Text.Json.JsonException
  HResult=0x80131500
  Message=The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
  Source=System.Text.Json
  StackTrace:
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, JsonReaderException ex)
   at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
   at System.Text.Json.JsonSerializer.ReadCore(Type returnType, JsonSerializerOptions options, Utf8JsonReader& reader)
   at System.Text.Json.JsonSerializer.ParseCore(String json, Type returnType, JsonSerializerOptions options)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
   at Oqtane.Repository.PermissionRepository.DecodePermissions(String PermissionStrings, Int32 SiteId, String EntityName, Int32 EntityId) in C:\Siliqon\oqtane\sbwalker.oqtane.framework\Oqtane.Server\Repository\PermissionRepository.cs:line 163
   at Oqtane.Repository.PermissionRepository.UpdatePermissions(Int32 SiteId, String EntityName, Int32 EntityId, String Permissions) in C:\Siliqon\oqtane\sbwalker.oqtane.framework\Oqtane.Server\Repository\PermissionRepository.cs:line 71
   at Oqtane.Repository.PageRepository.DeletePage(Int32 PageId) in C:\Siliqon\oqtane\sbwalker.oqtane.framework\Oqtane.Server\Repository\PageRepository.cs:line 65
   at Oqtane.Controllers.PageController.Delete(Int32 id) in C:\Siliqon\oqtane\sbwalker.oqtane.framework\Oqtane.Server\Controllers\PageController.cs:line 89
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.<>c__DisplayClass33_0.<WrapVoidMethod>b__0(Object target, Object[] parameters)
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.VoidResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()

Inner Exception 1:
JsonReaderException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0.

Upgrade Oqtane to .NET Core 3.0 Preview6

Microsoft released .NET Core 3.0 Preview 5 on May 6. Currently Oqtane only runs on Preview 4 and will not compile on Preview 5. We should try to stay up to date with the latest Microsoft releases.

Delete User Experience

The current admin user experience in Oqtane diplays a Delete option for each entity record in the summary grid view. When the user selects the Delete option it displays a distinct Delete component where all of the fields for the entity are displayed in readonly mode. The user can choose to Delete or Cancel - and if they choose Delete it removes the record ( either via soft delete or hard delete depending on the entity ).

The reason for this approach is that Delete is a serious/permanent action, so you want to provide the opportunity for a user to either confirm or cancel the action. Displaying a Delete component accomplishes this goal; however, the downside is that requires the development and ongoing maintenance of an additional component which contains more code/functionality than is truly necessary to accomplish the original goal.

Another common approach in product development is to simply display a Confirmation popup dialog when a user selects Delete from the summary grid view. This still provides the opportunity for a user to confirm/cancel the action - and it eliminates the need for creating a separate dedicated Delete component.

I would like to hear some feedback on whether Oqtane should transition to the Confirmation popup dialog approach.

Update Bootstrap to 4.3.1 and fully utilize CDN

Bootstrap is currently using a Beta version of 4.0.0. The CSS is currently loaded via a local minified CSS file. However, the JS is loaded via CDN. Bootstrap should be upgraded to 4.3.1 and fully loaded via CDN.

Lack of documentation comments

I noticed there's no documentation in the code. This was a big issue with DNN which had no documentation comments for many years before some users started adding them. Lack of proper documentation was a major pain for DNN. I hope this is not repeated again with Oqtane. Starting to add documentation comments early on before it becomes a daunting task will make it simpler and encourage developers to participate in advancing the framework. These comments help a lot also when using a documentation generator.

Azure Function Apps

As we move more and more to the cloud, things like function apps make more sense when it comes to deploy ability and maintenance. Have you thought about examples where you decouple the server/ui and creating server less function endpoints?

Recommended Name Changes

Based on the terms used in other platforms, I would suggest a rename of the Skins concept to be Theme. This more closely aligns to other tools, which will help with understanding/adoptions.

I would gladly submit a PR for this, but would want to be sure it was desired before I do

Need tooltips to explain what some of the input fields are

There's no documentation and no tooltips to tell us what some of the vague options are.
For example, the Path field when creating a new page. I don't know what that this. A tooltip next to the label explaining what the field is for and an example value goes a long way.

3rd Party Control Support

One of the problems with a lot of frameworks like these is they are built w/out any 3rd party controls like DevExpress, Telerik, SynFusion, etc. So then when you start programming, some of the UI elements tend to look "off" because maybe some of the pages that are defied in the framework havent been updated to use the other control sets.

I havent looked at the framework fully yet, but it would be nice if you implemented helpers to render out controls that way they could be overridden easily if we wanted to use DevExpress editors and such.

Or is that like a "theme" instead?

Module: Cannot insert the value NULL into column 'Title', table 'Oqtane.dbo.PageModule'

To reproduce:

  1. Log in as host
  2. Click Pencil to edit page
  3. Click Hamburger menu to open Admin panel
  4. Add counter module to page
  5. get the following error:
Microsoft.EntityFrameworkCore.DbUpdateException
  HResult=0x80131500
  Message=An error occurred while updating the entries. See the inner exception for details.
  Source=Microsoft.EntityFrameworkCore.Relational
  StackTrace:
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(DbContext _, ValueTuple`2 parameters)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at Oqtane.Repository.DBContextBase.SaveChanges() in C:\Siliqon\oqtane\sbwalker.oqtane.framework\Oqtane.Server\Repository\Context\DBContextBase.cs:line 91
   at Oqtane.Repository.PageModuleRepository.AddPageModule(PageModule PageModule) in C:\Siliqon\oqtane\sbwalker.oqtane.framework\Oqtane.Server\Repository\PageModuleRepository.cs:line 41
   at Oqtane.Controllers.PageModuleController.Post(PageModule PageModule) in C:\Siliqon\oqtane\sbwalker.oqtane.framework\Oqtane.Server\Controllers\PageModuleController.cs:line 44
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()

Inner Exception 1:
SqlException: Cannot insert the value NULL into column 'Title', table 'Oqtane.dbo.PageModule'; column does not allow nulls. INSERT fails.
The statement has been terminated.

CounterError

Improve Theme #1 Layout & Structure

Currently the layout of Theme 1 is done using a container for the main content that adds some unnatural padding to the left & right, which when showcasing the power of things looks unusual. With a left-menu structure this should be updated to use a fluid container to properly manage the layout and improve look and feel.

move code to page.razor.cs

What you think about move code into page.razor.cs file?
Visual Studio has better intellisense in .cs than .razor files

DB Connections Support Azure SQL Access Tokens

Ability to support connecting to Azure SQL using Managed Identities. We host our DBs in azure, we create a managed identity for the app, and give it auth to the DB it needs, this means we don't need to store usernames and passwords in the connection string thus its more secure.

I would think a toggle on the tenant creation.

REF:
https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi

public MyDatabaseContext(SqlConnection conn) : base(conn, true)
{
    conn.ConnectionString = WebConfigurationManager.ConnectionStrings["MyDbConnection"].ConnectionString;
    // DataSource != LocalDB means app is running in Azure with the SQLDB connection string you configured
    if(conn.DataSource != "(localdb)\\MSSQLLocalDB")
        conn.AccessToken = (new AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/").Result;

    Database.SetInitializer<MyDatabaseContext>(null);
}

Global Users/Permissions

It would be great to be able to create some global users that have access into each "tenant" with a set of defined roles/permissions.

We use multi tenancy frameworks as a way to isolate our clients, but our internal people could work on multiple accounts, its not like their permissions change from tenant to tenant, so in most frameworks we have to create users in each tenant then assigned roles/permissions. Some of this can be automatic behind the scenes for new tenants when we add them, otherwise we have to run scripts that update 50+ DB with a new user or a new role. But we also need the ability to have external users from the client access things, which would be setup in the tenant db as normal.

Note: 1 DB with multiple tenants accessing the same DB is not a viable solution when you need to maintain tenancy data isolation. IE: Healthcare or competing companies.

From the "host" it would be great to be able to create the user and assign the roles/permissions, if behind the scene it "syncs" these accounts/roles/permissions its fine also, but not having to do it via sql scripts or migrations would be wonderful :).

Page Not Found Handling

When a Url is manually entered into the browser and the path does not match a page defined in the database for the site, the system should respond with a Page Not Found message

Question - Oqtane Blazor Routing Diagram

Is there a diagram / flow chart showing how the routing is handled for Oqtane? I am having a hard time trying to piece together in which order components are built buy the system to handle a routing request.

Improve Action Link to Support Different Button Types

UI/UX standards indicate that deletion operations should be indicated with a red color. The control should support the designation of different types based on the theme. Such as btn-primary (the default) and btn-danger, or otherwise.

Introduce IRepository<TType>

IMHO introducing a IRepository<TType> will save time instead of creating I{Type}Repository for every entity

For instance IJobRepository will be:

public interface IJobRepository : IRepository<Job>
{
}

instead of

public interface IJobRepository
{
    IEnumerable<Job> GetJobs();
    Job AddJob(Job Job);
    Job UpdateJob(Job Job);
    Job GetJob(int JobId);
    void DeleteJob(int JobId);
}

or we could implement the generic repository directly from within JobRepository

Sometimes we may need to create custom on such IUserRepository:

public interface IUserRepository<User> : IRepository<User>
{
    User GetUser(string Username);
}

"Error Loading Module Container"

Steps to reproduce issue:

  1. Log in as Host.
  2. Open hamburger menu
  3. Select HelloWorld for Module
  4. Select Top Pane for Pane
  5. Do not select a container (leave it as 'select container')
  6. Press the button to Add Module To Page

The screen will say "Error Loading Module Container"

Expected Result:

  • The module will not show this error

Note: The only way to clear this is to go to the database and remove the latest record in the PageModule table and then the latest record in the Module table.

Discussion

  • Rather than prevent a person from adding a module without a container, I suggest we allow a person to add a module without a container but not have it throw an error?

  • I would be willing to work on this, but did not want to do so without guidance

Client-side Routing Broken in Preview6

Whether you are running the application in a client-side or server-side hosting model, it is a SPA and relies on client-side routing. In ASP.NET Core 3 Preview6 the client-side routing is broken. Currently in the server-side hosting model, every time you click a navigation link from the menu, it displays the message โ€œAttempting to reconnect to the serverโ€ and it reloads the entire page ( and never retains any application state ). In the client-side model, when you click a navigation link it displays the initial splash page image for Oqtane and then renders the entire page ( and never retains any application state ).

Policy (Permissions) instead of Role

In some controller you are using only AdminRole, why you don't use a framework built-in policy?
With policy even another role with specific policy (permission) can delete, add, edit, etc...

As example in UserController something like:

        // DELETE api/<controller>/5?siteid=x
        [HttpDelete("{id}")]
        [Authorize(Roles = Constants.AdminRole, Policy = Constants.DeleteUser)]
        public void Delete(int id, string siteid)

instead of

        // DELETE api/<controller>/5?siteid=x
        [HttpDelete("{id}")]
        [Authorize(Roles = Constants.AdminRole)]
        public void Delete(int id, string siteid)

The type or namespace name 'RenderTreeBuilder' does not exist ....

Using:
VS Community 2019 Preview 16.3.0,
.NET Core 3.0 Preview 8 SDK (3.0.0-preview8-013656). Also tried updating to preview9-014004 with same result. These are the latest versions available as of today (14 Sep).

Build fails with error:
The type or namespace name 'RenderTreeBuilder' does not exist in the namespace 'Microsoft.AspNetCore.Components.Rendering'

in ~50 generated code files (e.g. Oqtane.Client\obj\Debug\netstandard2.0\RazorDeclaration\Modules\Counter\Index.razor.g.cs)

I did note the compatibility requirements mentioned on https://github.com/oqtane/oqtane.framework however, it does not seem possible to download 3.0.0-preview8.19405.7 now.

Potential issue scaling out Oqtane

I've been reading through some of the code and I have a interest in NoSQL solutions (MongoDB is my preferred NoSQL of choice). As I was looking around how the code interacts with the SQL database as it sits now I see potential areas of improvement:

  1. Create a IDatabase interface that the modules can then use for CRUD operations. This would allow the creation of different database providers that can be switched out at startup. I understand this would be a quiet large task to undertake, but feel it would allow a much more flexible system to be built.

  2. If Oqtane was deployed to a system that auto-scales (like Kubernetes in my instance and I'm sure something like Azure) doing a replace on the app settings file would only change the one pod instance that did the install and all other pods wouldn't get this change. There are ways around this with persistent volume claims but its not a very straight forward process. Could thought be given to how this could be handled in a scalable environment?

But other then that this seems like an amazing framework and should get people up and running with Blazor and a website very easily. I cant wait to get my hands into creating some modules and themes for this.

Use EditForm

There is a reason why you don't use Blazor built-in EditForm in Add and Edit pages?

How to set-up after clone?

I tried the following:

  1. clone this repo
  2. open sln file (just open)
    default: Debug | Any CPU | Oqtane.Server
  3. build
  4. hit F5
    http://localhost:44357/ is opened but nothing is displayed? (But title displayed is oqtane.)
    What am I missing?

User Not Immediately Logged In Using Server-Side Blazor

When running on server-side Blazor ( SignalR ) if you select the Login button and enter any valid user credentials ( ie. host/host ) the user does not appear to be immediately logged in - you need to navigate to another page in the site ( ie. Page2, Page3 ) and then the UI will be refreshed to reflect that you are logged in. This is because the JSInterop call in the SiteRouter to get the cookie for the user throws an exception. This problem does not exist when running on client-side Blazor ( Wasm ).

'RenderTreeBuilder' does not contain a definition for 'SetUpdatesAttributeName' in Oqtane.Client

Hello

I'm running VS 16.3 preview 1 - but still on Blazor preview 6. But I've uninstalled the old Blazor extension

Just cloned Oqtane repo but can't build the client project due to 57 errors coming from the auto-generated *.razor.g.cs files (where * = index, installer, controlpanel, add, delete, edit, components)

From my (limited) experience with Blazor this usually comes from the html part of these components, but I can't see anything illegal there...

Any ideas?

Selected Page Layout not honored

To reproduce:

  1. Log in as Host and create a new page
  2. Select "horizontal layout"
  3. When viewing the page, click the pencil icon to see the layout, it will say Top Pane / Bottom Pane and the database will be set to Left;Right
  4. Change the layout to "vertical layout"
  5. When viewing the page, click the pencil icon to see the layout, it will say Top Pane / Bottom Pane and the database will be set to Top;Bottom

What's the roadmap for Oqtane?

What's the roadmap for Oqtane? I would like to see what features are intended to be released in every quarter or even better every month.

Personally, I would like to see this framework evolve into one that supports modules/plugins/extensions and themes like DNN. Modules should be able to use third party UI controls without affecting the framework or other installed modules.

Profile Management

An admin module is needed for managing Profile properties. This module should be developed in the standard manner ( with Index, Add, Edit, Delete capabilities ) and be exposed on the Admin Dashboard.

Entities from Interfaces and DateTime

Why not have the classes for audit/soft deletes etc inherit from some base classes instead of implementing the properties in every class?

Also should probably use UTC times or be configurable. I dont remember if EFCore3 now allows to use the SQL datatime value instead which would be preferred. (EX: If you have a default value set in SQL currently EF doesnt honor it with EF.)

EX of classes:

 [JsonObject(NamingStrategyType = typeof(DefaultNamingStrategy))]
    public partial class Address: AuditBase<int>
    {
        #region Keys

        /// <inheritdoc />
        ///<summary>
        /// Identifier for an address.
        ///</summary>
        [Column("AddressId")]
        [Display(Name = "Address Id", Description = "Identifier for an address.", Prompt = "Address Id")]
        public override int Id { get; set; }

        #endregion

        #region Scalars

        ///<summary>
        /// Line 1 of the address.
        ///</summary>
        [Required]
        [StringLength(50, ErrorMessage="Address 1 max length is 50.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Address 1", Description = "Line 1 of the address.", Prompt = "Address 1")]
        public string Address1 { get; set; }

        ///<summary>
        /// Line 2 of the address.
        ///</summary>
        [StringLength(50, ErrorMessage="Address 2 max length is 50.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Address 2", Description = "Line 2 of the address.", Prompt = "Address 2")]
        public string Address2 { get; set; }

        ///<summary>
        /// 3rd line of the address.  Used in European addresses.
        ///</summary>
        [StringLength(50, ErrorMessage="Address 3 max length is 50.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Address 3", Description = "3rd line of the address.  Used in European addresses.", Prompt = "Address 3")]
        public string Address3 { get; set; }

        ///<summary>
        /// City of the location.
        ///</summary>
        [Required]
        [StringLength(35, ErrorMessage="City max length is 35.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="City", Description = "City of the location.", Prompt = "City")]
        public string City { get; set; }

        ///<summary>
        /// State of the address.
        ///</summary>
        [StringLength(2, ErrorMessage="State max length is 2.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="State", Description = "State of the address.", Prompt = "State")]
        public string State { get; set; }

        ///<summary>
        /// Zip 5 of the address.
        ///</summary>
        [StringLength(5, ErrorMessage="Zip max length is 5.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Zip", Description = "Zip 5 of the address.", Prompt = "Zip")]
        public string Zip { get; set; }

        ///<summary>
        /// Zip plus 4 of the address.
        ///</summary>
        [StringLength(4, ErrorMessage="Zip 4 max length is 4.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Zip 4", Description = "Zip plus 4 of the address.", Prompt = "Zip 4")]
        public string Zip4 { get; set; }

        ///<summary>
        /// The postal code of the address. If a zip+4 is available for a US address this will be formatted as xxxxx-xxxx. Otherwise it will contain the 5-digit zip or the Canadian postal code.
        ///</summary>
        [Required]
        [StringLength(15, ErrorMessage="Postal Code max length is 15.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Postal Code", Description = "The postal code of the address. If a zip+4 is available for a US address this will be formatted as xxxxx-xxxx. Otherwise it will contain the 5-digit zip or the Canadian postal code.", Prompt = "Postal Code")]
        public string PostalCode { get; set; }

        ///<summary>
        /// Code of the country.
        ///</summary>
        [StringLength(3, ErrorMessage="Country Code max length is 3.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Country Code", Description = "Code of the country.", Prompt = "Country Code")]
        public string CountryCode { get; set; }

        ///<summary>
        /// Federal Information Processing Standard Code that uniquely identifies counties and county equivalents in ht eUnited States, certain US possession, and certain freely associated
        ///</summary>
        [StringLength(5, ErrorMessage="FIPS Code max length is 5.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="FIPS Code", Description = "Federal Information Processing Standard Code that uniquely identifies counties and county equivalents in ht eUnited States, certain US possession, and certain freely associated", Prompt = "FIPS Code")]
        public string FIPSCode { get; set; }

        ///<summary>
        /// Reutrn code provided by the address hygiene process.
        ///</summary>
        [StringLength(1, ErrorMessage="Address Return Code max length is 1.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Address Return Code", Description = "Reutrn code provided by the address hygiene process.", Prompt = "Address Return Code")]
        public string AddressReturnCode { get; set; }

        ///<summary>
        /// Latitude of the address.
        ///</summary>
        [Display(Name ="Latitude", Description = "Latitude of the address.", Prompt = "Latitude")]
        public decimal? Latitude { get; set; }

        ///<summary>
        /// Longitude based on the address.
        ///</summary>
        [Display(Name ="Longitude", Description = "Longitude based on the address.", Prompt = "Longitude")]
        public decimal? Longitude { get; set; }

        ///<summary>
        /// Indicator as to the level that the longitude and latitude were calculated to.
        ///</summary>
        [StringLength(1, ErrorMessage="Geo Coding Accuracy Code max length is 1.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Geo Coding Accuracy Code", Description = "Indicator as to the level that the longitude and latitude were calculated to.", Prompt = "Geo Coding Accuracy Code")]
        public string GeoCodingAccuracyCode { get; set; }

        ///<summary>
        /// Date that the reco
        ///</summary>
        [Display(Name ="Last Hygiene Date", Description = "Date that the reco", Prompt = "Last Hygiene Date")]
        public DateTime? LastHygieneDate { get; set; }

        ///<summary>
        /// Matchkey used for a quick match of the address.
        ///</summary>
        [Required]
        [StringLength(250, ErrorMessage="Address Match Key max length is 250.")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        [Display(Name ="Address Match Key", Description = "Matchkey used for a quick match of the address.", Prompt = "Address Match Key")]
        public string AddressMatchKey { get; set; }

        #endregion

        #region Reverse Navigation


        ///<summary>
        /// Parent Address pointed to by AddressHygieneQueue.AddressId
        ///</summary>
        [JsonIgnore]
        public List<AddressHygieneQueue> AddressAddressHygieneQueue_Reverse { get; set; }

        ///<summary>
        /// Parent Address pointed to by CompanyAddress.AddressId
        ///</summary>
        [JsonIgnore]
        public List<CompanyAddress> AddressCompanyAddress_Reverse { get; set; }

        ///<summary>
        /// Parent Address pointed to by ContactAddress.AddressId
        ///</summary>
        [JsonIgnore]
        public List<ContactAddress> AddressContactAddress_Reverse { get; set; }

        ///<summary>
        /// Parent Address pointed to by ContactChannelInfo.AddressId
        ///</summary>
        [JsonIgnore]
        public List<ContactChannelInfo> AddressContactChannelInfo_Reverse { get; set; }

        ///<summary>
        /// Parent Address pointed to by Subscriber.AddressId
        ///</summary>
        [JsonIgnore]
        public List<Subscriber> AddressSubscriber_Reverse { get; set; }

        #endregion

        public Address()
        {

            OnCreated();

        }
        partial void OnCreated();
    }
[JsonObject(NamingStrategyType = typeof(DefaultNamingStrategy))]
    public class AuditBase<T> : IEntity<T>
    {
        [Column("Inserted", TypeName = "datetime")]
        [Required(ErrorMessage = "Inserted  is required")]
        [Display(Name = "Inserted", Order = 9000)]
        [ReadOnly(true)]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy hh:mm tt}")]
        [DefaultValue("Getdate()")]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public virtual DateTime Inserted { get; set; }

        [Column("InsertedBy")]
        [MaxLength(128)]
        [StringLength(128)]
        [Required(ErrorMessage = "Inserted By  is required")]
        [Display(Name = "Inserted By", Order = 9001)]
        public virtual string InsertedBy { get; set; }

        [Column("Updated", TypeName = "datetime")]
        [Required(ErrorMessage = "Updated  is required")]
        [Display(Name = "Updated", Order = 9002)]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy hh:mm tt}")]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [DefaultValue("Getdate()")]
        public virtual DateTime Updated { get; set; }

        [Column("UpdatedBy")]
        [MaxLength(128)]
        [StringLength(128)]
        [Required(ErrorMessage = "Updated By  is required")]
        [Display(Name = "Updated By", Order = 9003)]
        public virtual string UpdatedBy { get; set; }

        [Column("EditCount", TypeName = "int")]
        [Required(ErrorMessage = "Edit Count  is required")]
        [Display(Name = "Edit Count", Order = 904)]
        [ConcurrencyCheck]
        public virtual int EditCount { get; set; }

        public bool IsTransient()
        {
            if (EqualityComparer<T>.Default.Equals(Id, default))
            {
                return true;
            }

            //Workaround for EF Core since it sets int/long to min value when attaching to dbcontext
            if (typeof(T) == typeof(int))
            {
                return Convert.ToInt32(Id) <= 0;
            }

            if (typeof(T) == typeof(long))
            {
                return Convert.ToInt64(Id) <= 0;
            }

            return false;
        }

        public virtual T Id { get; set; }
    }
 public interface IEntity : IEntity<int>
    {

    }

Edit buttons disappear on refresh

I noticed that when I am on the modules page and I click refresh in chrome, after the refresh, the edit buttons are not visible.

Before refreshing.

before

After refreshing

after

Table Names/Prefix

Looking at the SQL Scripts, what do you think about prefixing all the tables with "oqt" or something, if applying this to an existing DB there could be conflicts, plus when running code generation it would be nice to say ignore tables starting with "xxx".

Also not sure what Alias is. Can a Tenant have multiple sites? This table seems to be a junction between Tenant and Site, so shouldnt the name be TenantSites?

I assume the Master DB is installed to its own db?

Oqtane.org Forums

Did something on the Oqtane site change? I can't access the community/forums page. It says I don't have the access to view the page.

Add Page doesn't reload ContentPanel pages

Add new page doesn't reload ContentPanel pages available.

I have to move to following code into OnParameterSet or there is another solution to reload it?

protected override void OnParametersSet()
{
    pages = new List<Page>();

    foreach(Page p in PageState.Pages)
    {
        if (UserSecurity.IsAuthorized(PageState.User, "View", p.Permissions))
        {
            pages.Add(p);
        }
    }
}

Edit Mode not working for modules

To reproduce:

  1. Create a new page
  2. Add the Counter module to the page
  3. When viewing the page in Edit mode (as the Host account) the controls to edit the module will not show

Oqtane should work with SqlLite and ProgreSQL

One of the major advantages of .NET Core is that it is cross-platform. We need to ensure that we support databases that are more commonly used on Linux and Mac, and avoid a specific dependency on SQL Server (even though it is now available on Linux)

Cannot create a new page

Create new site
Log in as host
Try to add a new page to the site
Get the following error:

[2019-11-12T02:51:47.988Z] Error: System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 0.
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializerCycleDetected(Int32 maxDepth)
at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteCore(Utf8JsonWriter writer, PooledByteBufferWriter output, Object value, Type type, JsonSerializerOptions options)
at System.Text.Json.JsonSerializer.WriteCore(PooledByteBufferWriter output, Object value, Type type, JsonSerializerOptions options)
at System.Text.Json.JsonSerializer.WriteCoreString(Object value, Type type, JsonSerializerOptions options)
at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)
at Oqtane.Services.LogService.Log(Nullable1 PageId, Nullable1 ModuleId, Nullable`1 UserId, String category, String feature, LogFunction function, LogLevel level, Exception exception, String message, Object[] args) in C:\Users\Michael\Source\Repos\ADefWebserver\oqtane.framework\Oqtane.Client\Services\LogService.cs:line 54
at Oqtane.Modules.ModuleBase.Log(LogLevel level, Exception exception, String message, Object[] args) in C:\Users\Michael\Source\Repos\ADefWebserver\oqtane.framework\Oqtane.Client\Modules\ModuleBase.cs:line 160
at Oqtane.Modules.ModuleBase.Logger.LogError(Exception exception, String message, Object[] args) in C:\Users\Michael\Source\Repos\ADefWebserver\oqtane.framework\Oqtane.Client\Modules\ModuleBase.cs:line 219
at Oqtane.Modules.Admin.Pages.Add.SavePage() in C:\Users\Michael\Source\Repos\ADefWebserver\oqtane.framework\Oqtane.Client\Modules\Admin\Pages\Add.razor:line 323
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

Feature Request - Form Designer

Are there any plans to try and make a dynamic form designer? Kinda like ninja forms for WordPress. If not any ideas on where to start to build it?

Cleanup Reused/Duplicated Code Relating to Themes

Currently, in the Client library, multiple .cshtml files are performing the same actions with the results from the IThemeService (Formerly ISkinService).

These operations should be condensed and moved to a method implementation inside of the IThemeService to prevent fragility in management of the code-base going forward.

Items to consider moving to a method implementation:

  • Available Themes
  • Available Containers

This will substantially reduce the on-view code levels greatly.

I'll submit a PR for this, after my other PR is processed, but wanted to get this documented.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.