Ejemplo n.º 1
0
        public static void AddModelCollection(this ICmsConfig cmsConfig)
        {
            var config = cmsConfig.AddCollection <ModelEntity, ModelRepository>(
                Constants.ModelMakerAdminCollectionAlias,
                "Database",
                "MagentaPink10",
                "Models",
                x => { });

            config.SetTreeView(x => x.Name);

            config.SetListView(view =>
            {
                view.AddDefaultButton(DefaultButtonType.New);

                view.AddRow(row =>
                {
                    row.AddField(x => x.Name);
                    row.AddField(x => x.PluralName).SetName("Plural name");

                    row.AddDefaultButton(DefaultButtonType.Edit);
                });
            });

            config.SetNodeEditor(editor =>
            {
                editor.AddSection(section =>
                {
                    section.AddDefaultButton(DefaultButtonType.Up);
                    section.AddDefaultButton(DefaultButtonType.SaveExisting);
                    section.AddDefaultButton(DefaultButtonType.SaveNew);
                    section.AddDefaultButton(DefaultButtonType.Delete);

                    section.AddField(x => x.Name);

                    section.AddField(x => x.PluralName)
                    .SetName("Plural name");

                    section.AddField(x => x.IconColor)
                    .SetDetails(new MarkupString("See Shared Colors at <a href=\"https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/shared\">https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/shared</a>."))
                    .SetType(EditorType.Dropdown)
                    .SetDataCollection <EnumDataProvider <Color> >();

                    section.AddField(x => x.Icon)
                    .SetDetails(new MarkupString("See Fabric Core icons at <a href=\"https://developer.microsoft.com/en-us/fluentui#/styles/web/icons#available-icons\">https://developer.microsoft.com/en-us/fluentui#/styles/web/icons#available-icons</a>."));

                    section.AddField(x => x.Alias)
                    .SetName("Collection alias")
                    .SetType(EditorType.Readonly)
                    .VisibleWhen((m, s) => s == EntityState.IsExisting);

                    section.AddField(x => x.Output)
                    .SetDescription("Code will be generated for these items")
                    .SetType(EditorType.EnumFlagPicker)
                    .SetDataCollection <EnumDataProvider <OutputItem> >();

                    section.AddSubCollectionList("modelmaker::property");
                });
            });
        }
Ejemplo n.º 2
0
 public PageSetupResolver(
     ICmsConfig cmsConfig,
     ISetupResolver <ITypeRegistration, CustomTypeRegistrationConfig> typeRegistrationSetupResolver)
 {
     _cmsConfig = cmsConfig;
     _typeRegistrationSetupResolver = typeRegistrationSetupResolver;
 }
Ejemplo n.º 3
0
        // CRUD editor using a mapped repository
        public static void AddMappedCollection(this ICmsConfig config)
        {
            config.AddCollection <MappedEntity, MappedInMemoryRepository <MappedEntity, DatabaseEntity> >("mapped", icon: "git-compare", "Mapped entities", collection =>
            {
                collection
                .SetTreeView(EntityVisibilty.Hidden, x => x.Name)

                // adding a data view builder allows you to have multiple tabs in the list editor, each with a different
                // query associated with it
                .SetDataViewBuilder <DatabaseEntityDataViewBuilder>()
                .SetListEditor(editor =>
                {
                    editor.AddDefaultButton(DefaultButtonType.Return);
                    editor.AddDefaultButton(DefaultButtonType.New);

                    editor
                    .AddSection(section =>
                    {
                        // since the repository is mapped, the OrderBy query send to the IQueryable of the repository
                        // is based on DatabaseEntity, and not MappedEntity. because of this, the overload of SetOrderByExpression
                        // is used by which you can specify the type of entity
                        section.AddField(x => x.Name)
                        .SetOrderByExpression <DatabaseEntity, string?>(x => x.Name);
                        section.AddField(x => x.Description)
                        .SetOrderByExpression <DatabaseEntity, string?>(x => x.Description);

                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);
                    });
                });
            });
        }
Ejemplo n.º 4
0
        // CRUD editor with support for one-to-many relation + validation
        public static void AddCountryCollection(this ICmsConfig config)
        {
            config.AddCollection <Country>("country", "Countries", collection =>
            {
                collection
                .SetTreeView(x => x.Name)
                .SetRepository <JsonRepository <Country> >()
                .SetListView(view =>
                {
                    view.AddDefaultButton(DefaultButtonType.New);

                    view
                    .AddRow(row =>
                    {
                        row.AddField(p => p.Id.ToString()).SetName("ID");
                        row.AddField(p => p.Name);

                        row.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                .SetNodeEditor(editor =>
                {
                    editor
                    .AddDefaultButton(DefaultButtonType.SaveExisting)
                    .AddDefaultButton(DefaultButtonType.SaveNew);

                    editor.AddSection(section =>
                    {
                        section.AddField(x => x.Name);

                        // this property contains a list of people it is related to
                        // you can see it as a ICollection<TRelated> property in EF Core

                        // because this property has an RelationValidationAttribute, the CMS first checks if the
                        // selected values are valid, before allowing the user to save this entity.
                        // in this example, the user may only select up to two People per Country

                        section.AddField(x => x.People)
                        // a multi-select is a list of checkboxes
                        .SetType(EditorType.MultiSelect)
                        // this binds the PersonCollection to this collection
                        // the CMS must know what the foreign entity and key is, you need to specify it
                        .SetCollectionRelation <Person, int>(
                            // this selects which values are used as selected values
                            people => people.Select(p => p.Id),
                            // alias of the related collection
                            "person",
                            // this callback allows you to specify how the multi-select should look like
                            relation =>
                        {
                            relation
                            // when the user selects an element, the value that is used as Id is used
                            // to set the value of the property
                            .SetElementIdProperty(x => x.Id)
                            .SetElementDisplayProperties(x => x.Name, x => x.Email);
                        });
                    });
                });
            });
        }
Ejemplo n.º 5
0
        // CURD editor with validation attributes, custom editor and custom button panes
        public static void AddUserCollection(this ICmsConfig config)
        {
            config.AddCollection <User>("user", "Users", collection =>
            {
                collection
                .SetTreeView(EntityVisibilty.Hidden, x => x.Name)
                .SetRepository <JsonRepository <User> >()
                .SetListEditor(editor =>
                {
                    editor.AddDefaultButton(DefaultButtonType.Return);
                    editor.AddDefaultButton(DefaultButtonType.New);
                    // this pane button opens a sidepane displaying the ResetAllPane Razor component.
                    // this component must inherit BaseSidePane and allows for more complex flows and confirmations.
                    editor.AddPaneButton(typeof(ResetAllPane), "Reset all passwords", "trash");

                    // custom buttons are also allowed:
                    // editor.AddCustomButton<TActionHandler>(typeof(ButtonType));
                    // they must reference a BaseButton derived Razor component, as well as a ActionHandler which handles
                    // the click from the user.

                    editor
                    .AddSection(section =>
                    {
                        section.AddField(x => x.Name);
                        section.AddField(x => x.StartDate).SetType(EditorType.Date);

                        // this field uses a custom editor, which must inherit BaseEditor
                        section.AddField(x => x.Password).SetType(typeof(PasswordEditor));

                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);
                    });
                });
            });
        }
Ejemplo n.º 6
0
        /// <summary>
        /// This method adds the Model Maker plugin and collection to RapidCMS.
        /// </summary>
        /// <param name="cmsConfig"></param>
        /// <returns></returns>
        public static ICmsConfig AddModelMakerPlugin(this ICmsConfig cmsConfig)
        {
            cmsConfig.AddModelMakerPluginCore();

            cmsConfig.AddModelCollection();

            return(cmsConfig);
        }
Ejemplo n.º 7
0
 public static void AddActiveCollection(this ICmsConfig config)
 {
     config.AddCollection <Counter, BaseRepository <Counter> >("active", icon: "contacts", "Active Counter", collection =>
     {
         collection
         .SetTreeView(x => x.CurrentCount.ToString())
         .ConfigureByConvention(CollectionConvention.ListViewNodeView);
     });
 }
 public TreeElementsSetupResolver(ICmsConfig cmsConfig,
                                  ISetupResolver <IEnumerable <TreeElementSetup>, IEnumerable <ITreeElementConfig> > treeElementResolver,
                                  ISetupResolver <IEnumerable <TreeElementSetup>, IPlugin> pluginTreeElementResolver,
                                  IEnumerable <IPlugin> plugins)
 {
     _cmsConfig                 = cmsConfig;
     _treeElementResolver       = treeElementResolver;
     _pluginTreeElementResolver = pluginTreeElementResolver;
     _plugins = plugins;
 }
        public CmsRepositoryTypeResolver(ICmsConfig cmsConfig, IServiceProvider serviceProvider)
        {
            using var repositoryResolvingScope = serviceProvider.CreateScope();

            var types = cmsConfig.RepositoryTypes.Distinct();

            _repositoryTypes = types.ToDictionary(
                type => AliasHelper.GetRepositoryAlias(repositoryResolvingScope.ServiceProvider.GetRequiredService(type).GetType()));

            _originallyRegisterdRepositoriesToAlias = _repositoryTypes.ToDictionary(x => x.Value, x => x.Key);
        }
 public CollectionSetupResolver(ICmsConfig cmsConfig,
                                ISetupResolver <IEnumerable <ITreeElementSetup>, IEnumerable <ITreeElementConfig> > treeElementResolver,
                                ISetupResolver <IEntityVariantSetup, EntityVariantConfig> entityVariantResolver,
                                ISetupResolver <TreeViewSetup, TreeViewConfig> treeViewResolver,
                                ISetupResolver <ListSetup, ListConfig> listResolver,
                                ISetupResolver <NodeSetup, NodeConfig> nodeResolver)
 {
     _treeElementResolver   = treeElementResolver;
     _entityVariantResolver = entityVariantResolver;
     _treeViewResolver      = treeViewResolver;
     _listResolver          = listResolver;
     _nodeResolver          = nodeResolver;
     Initialize(cmsConfig);
 }
Ejemplo n.º 11
0
        // CRUD editor for simple POCO based on conventions
        public static void AddConventionCollection(this ICmsConfig config)
        {
            config.AddCollection <ConventionalPerson, JsonRepository <ConventionalPerson> >("person-convention", "People (by convention)", collection =>
            {
                collection.SetTreeView(x => x.Name);

                // The convention system resolves the configuration based on the [Display]-attributes placed on the properties of the model of this collection.
                // It uses the EditorTypeHelper.TryFindDefaultEditorType to resolve the best matching editor for the property.
                //
                // - The ListEditor will display a list editor with columns for every column with a [Display] attribute and use its Name and Description
                //   for displaying the name and description.
                //
                // - The ListView+NodeEditor will display a list view with columns for each column with a [Display] attribute with a defined ShortName.
                //   The corresponding node editor will display an editor with fields for each the properties that sport a [Display] attribute, and uses
                //   the Name and Description of said attribute.
                //
                // - The ListView will only display a readonly list view without edit options.
                collection.ConfigureByConvention(CollectionConvention.ListViewNodeEditor);
            });
        }
Ejemplo n.º 12
0
 public CollectionSetupResolver(ICmsConfig cmsConfig,
                                ISetupResolver <IEnumerable <TreeElementSetup>, IEnumerable <ITreeElementConfig> > treeElementResolver,
                                ISetupResolver <EntityVariantSetup, EntityVariantConfig> entityVariantResolver,
                                ISetupResolver <TreeViewSetup, TreeViewConfig> treeViewResolver,
                                ISetupResolver <ElementSetup, ElementConfig> elementResolver,
                                ISetupResolver <ListSetup, ListConfig> listResolver,
                                ISetupResolver <NodeSetup, NodeConfig> nodeResolver,
                                IRepositoryTypeResolver repositoryTypeResolver,
                                IEnumerable <IPlugin> plugins)
 {
     _cmsConfig              = cmsConfig;
     _treeElementResolver    = treeElementResolver;
     _entityVariantResolver  = entityVariantResolver;
     _treeViewResolver       = treeViewResolver;
     _elementResolver        = elementResolver;
     _listResolver           = listResolver;
     _nodeResolver           = nodeResolver;
     _repositoryTypeResolver = repositoryTypeResolver;
     _plugins = plugins;
     Initialize();
 }
        private void Initialize(ICmsConfig cmsConfig)
        {
            MapCollections(cmsConfig.CollectionsAndPages.SelectNotNull(x => x as CollectionConfig));

            void MapCollections(IEnumerable <CollectionConfig> collections)
            {
                foreach (var collection in collections.Where(col => !col.Recursive))
                {
                    if (!_collectionMap.TryAdd(collection.Alias, collection))
                    {
                        throw new InvalidOperationException($"Duplicate collection alias '{collection.Alias}' not allowed.");
                    }

                    var subCollections = collection.CollectionsAndPages.SelectNotNull(x => x as CollectionConfig);
                    if (subCollections.Any())
                    {
                        MapCollections(subCollections);
                    }
                }
            }
        }
Ejemplo n.º 14
0
        // CRUD editor for simple POCO based on conventions
        public static void AddConventionCollection(this ICmsConfig config)
        {
            config.AddCollection <ConventionalPerson, BaseRepository <ConventionalPerson> >("person-convention", "Settings", "Green20", "People (by convention)", collection =>
            {
                collection.SetTreeView(EntityVisibilty.Visible, x => x.Name);

                // The convention system resolves the configuration based on the [Display]-attributes placed on the properties of the model of this collection.
                // It uses the EditorTypeHelper.TryFindDefaultEditorType to resolve the best matching editor for the property.
                //
                // - The ListEditor will display a list editor with columns for every column with a [Display] attribute and use its Name and Description
                //   for displaying the name and description.
                //
                // - The ListView+NodeEditor will display a list view with columns for each column with a [Display] attribute with a defined ShortName.
                //   The corresponding node editor will display an editor with fields for each the properties that sport a [Display] attribute, and uses
                //   the Name and Description of said attribute.
                //
                // - The ListView will only display a readonly list view without edit options.
                collection.ConfigureByConvention(CollectionConvention.ListViewNodeEditor);

                // There are three combo's that should be used:
                // - collection.SetTreeView(EntityVisibilty.Visible, x => x.Property);
                // - collection.ConfigureByConvention(CollectionConvention.ListViewNodeEditor);

                // There are three combo's that should be used:
                // - collection.SetTreeView(EntityVisibilty.Hidden, x => x.Property);
                // - collection.ConfigureByConvention(CollectionConvention.ListView);

                // There are three combo's that should be used:
                // - collection.SetTreeView(EntityVisibilty.Visible, x => x.Property);
                // - collection.ConfigureByConvention(CollectionConvention.ListViewNodeView);

                // There are three combo's that should be used:
                // - collection.SetTreeView(EntityVisibilty.Hidden, x => x.Property);
                // - collection.ConfigureByConvention(CollectionConvention.ListEditor);


                // Sub collections are added to the node view / node editor when there are collections.
                collection.AddSelfAsRecursiveCollection();
            });
        }
Ejemplo n.º 15
0
        // CRUD editor with validation attributes, custom editor and custom button panes
        public static void AddUserCollection(this ICmsConfig config)
        {
            // the CMS users https://ionicons.com/, so use the name of any Ion Icon as icon for a collection
            config.AddCollection <User, BaseRepository <User> >("user", "UserFollowed", "BlueMagenta30", "Users", collection =>
            {
                collection
                .SetTreeView(EntityVisibilty.Hidden, x => x.Name)
                .SetListEditor(editor =>
                {
                    editor.AllowReordering(true);

                    // you can control the number of entities on a single page
                    editor.SetPageSize(20);

                    editor.AddDefaultButton(DefaultButtonType.Return);
                    editor.AddDefaultButton(DefaultButtonType.New);
                    // this pane button opens a sidepane displaying the ResetAllPane Razor component.
                    // this component must inherit BaseSidePane and allows for more complex flows and confirmations.
                    editor.AddPaneButton(typeof(ResetAllPane), "Reset all passwords", "LockSolid");

                    // custom buttons are also allowed:
                    // editor.AddCustomButton<TActionHandler>(typeof(ButtonType));
                    // they must reference a BaseButton derived Razor component, as well as a ActionHandler which handles
                    // the click from the user.

                    editor
                    .AddSection(section =>
                    {
                        section.AddField(x => x.Name);

                        // this field uses a custom editor, which must inherit BaseEditor
                        section.AddField(x => x.Password).SetType(typeof(PasswordEditor));

                        // even though some properties on User are required, saving a User with only its Name set is allowed
                        // since this editor cannot touch those required properties.
                        // if all displayed properties on a model are valid, the whole model is considered valid, as the user
                        // will be unable to make the model valid otherwise.
                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);

                        section.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                .SetNodeEditor(editor =>
                {
                    editor
                    .AddSection(section =>
                    {
                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);

                        section.AddField(x => x.Name);
                        section.AddField(x => x.StartDate).SetType(EditorType.Date);

                        // this field uses a custom editor, which must inherit BaseEditor
                        section.AddField(x => x.Password).SetType(typeof(PasswordEditor));

                        // some default editors (like FileUploadEditor) require custom components, so they must be added using their full classname
                        // NoPreview is a default component indicating this upload editor has no preview of the file

                        // the file upload handler is different between ServerSide and WebAssembly, so only its interface is added here
                        // and via DI the correct handler is resolved. it's also allowed to reference the correct handler here (for example: Base64TextFileUploadHandler)
                        // to allow for per input configuration
                        // AND dependency injection in Blazor has trouble resolving generic types (like ApiFileUploadHandler<Base64TextFileUploadHandler>) so it's better
                        // to reference simple interfaces or types
                        section.AddField(x => x.FileBase64).SetType(typeof(FileUploadEditor <ITextUploadHandler, NoPreview>))
                        .SetName("User file");

                        // ImagePreview is a custom component derived from BasePreview to display the uploaded image
                        section.AddField(x => x.ProfilePictureBase64).SetType(typeof(FileUploadEditor <IImageUploadHandler, ImagePreview>))
                        .SetName("User picture");

                        section.AddField(x => x.Integer).SetType(EditorType.Numeric);
                        section.AddField(x => x.Double).SetType(EditorType.Numeric);
                    });
                });
            });
        }
Ejemplo n.º 16
0
        // CRUD editor with validation attributes, custom editor and custom button panes
        public static void AddUserCollection(this ICmsConfig config)
        {
            // the CMS users https://ionicons.com/, so use the name of any Ion Icon as icon for a collection
            config.AddCollection <User, JsonRepository <User> >("user", icon: "contacts", "Users", collection =>
            {
                collection
                .SetTreeView(EntityVisibilty.Hidden, x => x.Name)
                .SetListEditor(editor =>
                {
                    // you can control the number of entities on a single page
                    editor.SetPageSize(2);

                    editor.AddDefaultButton(DefaultButtonType.Return);
                    editor.AddDefaultButton(DefaultButtonType.New);
                    // this pane button opens a sidepane displaying the ResetAllPane Razor component.
                    // this component must inherit BaseSidePane and allows for more complex flows and confirmations.
                    editor.AddPaneButton(typeof(ResetAllPane), "Reset all passwords", "trash");

                    // custom buttons are also allowed:
                    // editor.AddCustomButton<TActionHandler>(typeof(ButtonType));
                    // they must reference a BaseButton derived Razor component, as well as a ActionHandler which handles
                    // the click from the user.

                    editor
                    .AddSection(section =>
                    {
                        section.AddField(x => x.Name);

                        // this field uses a custom editor, which must inherit BaseEditor
                        section.AddField(x => x.Password).SetType(typeof(PasswordEditor));

                        // even though some properties on User are required, saving a User with only its Name set is allowed
                        // since this editor cannot touch those required properties.
                        // if all displayed properties on a model are valid, the whole model is considered valid, as the user
                        // will be unable to make the model valid otherwise.
                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);

                        section.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                .SetNodeEditor(editor =>
                {
                    editor
                    .AddSection(section =>
                    {
                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);

                        section.AddField(x => x.Name);
                        section.AddField(x => x.StartDate).SetType(EditorType.Date);

                        // this field uses a custom editor, which must inherit BaseEditor
                        section.AddField(x => x.Password).SetType(typeof(PasswordEditor));

                        // some default editors (like FileUploadEditor) require custom components, so they must be added using their full classname
                        // NoPreview is a default component indicating this upload editor has no preview of the file
                        section.AddField(x => x.FileBase64).SetType(typeof(FileUploadEditor <Base64TextFileUploadHandler, NoPreview>))
                        .SetName("User file");

                        // ImagePreview is a custom component derived from BasePreview to display the uploaded image
                        section.AddField(x => x.ProfilePictureBase64).SetType(typeof(FileUploadEditor <Base64ImageUploadHandler, ImagePreview>))
                        .SetName("User picture");

                        section.AddField(x => x.Integer).SetType(EditorType.Numeric);
                        section.AddField(x => x.Double).SetType(EditorType.Numeric);
                    });
                });
            });
        }
Ejemplo n.º 17
0
        // CRUD editor with support for one-to-many relation + validation
        public static void AddCountryCollection(this ICmsConfig config)
        {
            config.AddCollection <Country>("country", "Countries", collection =>
            {
                collection
                .SetTreeView(x => x.Name)
                .SetRepository <JsonRepository <Country> >()
                .SetListView(view =>
                {
                    view.AddDefaultButton(DefaultButtonType.New);

                    view.SetPageSize(2);

                    view
                    .AddRow(row =>
                    {
                        row.AddField(p => p.Id.ToString())
                        .SetName("ID").SetType(DisplayType.Pre);

                        // by specifying SetOrderExpression you can allow the user to sort the data on that column
                        // giving it a default order will cause this column to be ordered when the user opens the view
                        row.AddField(p => p.Name)
                        .SetOrderByExpression(p => p.Name, OrderByType.Ascending);

                        // multiple columns can be ordered at once, and the OrderBys stack from left to right,
                        // so the Countries in this example will always be first ordered by Name, then by Metadata.Continent
                        row.AddField(p => p.Metadata.Continent)
                        .SetOrderByExpression(p => p.Metadata.Continent);

                        row.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                .SetNodeEditor(editor =>
                {
                    editor
                    // the Up button allows users to get one level up (based upon the tree)
                    .AddDefaultButton(DefaultButtonType.Up, "Back to list", "list")
                    .AddDefaultButton(DefaultButtonType.SaveExisting)
                    .AddDefaultButton(DefaultButtonType.SaveNew);

                    editor.AddSection(section =>
                    {
                        section.AddField(x => x.Name);
                        section.AddField(x => x.Metadata.Continent);

                        // this property contains a list of people it is related to
                        // you can see it as a ICollection<TRelated> property in EF Core

                        // because this property has an RelationValidationAttribute, the CMS first checks if the
                        // selected values are valid, before allowing the user to save this entity.
                        // in this example, the user may only select up to two People per Country

                        section.AddField(x => x.People)
                        // a multi-select is a list of checkboxes
                        .SetType(EditorType.MultiSelect)
                        // this binds the PersonCollection to this collection
                        // the CMS must know what the foreign entity and key is, you need to specify it
                        .SetCollectionRelation <Person, int>(
                            // this selects which values are used as selected values
                            people => people.Select(p => p.Id),
                            // alias of the related collection
                            "person",
                            // this callback allows you to specify how the multi-select should look like
                            relation =>
                        {
                            relation
                            // when the user selects an element, the value that is used as Id is used
                            // to set the value of the property
                            .SetElementIdProperty(x => x.Id)
                            .SetElementDisplayProperties(x => x.Name, x => x.Email);
                        });
                    });
                });
            });
        }
Ejemplo n.º 18
0
        // CRUD editor with support for one-to-many relation + validation
        public static void AddCountryCollection(this ICmsConfig config)
        {
            config.AddCollection <Country, BaseRepository <Country> >("country", "Nav2DMapView", "Blue10", "Countries", collection =>
            {
                // this collection uses a custom validator next to the data annotation validation
                collection.AddEntityValidator <CountryValidator>(
                    new CountryValidator.Config
                {
                    ForbiddenContinentName = "fdsafdsa",
                    ForbiddenCountryName   = "fdsa"
                });

                collection
                // Set showEntities to true to have this collection to fold open on default
                .SetTreeView(x => x.Name, showEntitiesOnStartup: false)
                .SetListView(view =>
                {
                    view.AddDefaultButton(DefaultButtonType.New);

                    view.SetPageSize(10);

                    view
                    .AddRow(row =>
                    {
                        row.AddField(p => p.Id.ToString())
                        .SetName("ID").SetType(DisplayType.Pre);

                        // by specifying SetOrderExpression you can allow the user to sort the data on that column
                        // giving it a default order will cause this column to be ordered when the user opens the view
                        row.AddField(p => p.Name)
                        .SetOrderByExpression(p => p.Name, OrderByType.Ascending);

                        // multiple columns can be ordered at once, and the OrderBys stack from left to right,
                        // so the Countries in this example will always be first ordered by Name, then by Metadata.Continent
                        row.AddField(p => p.Metadata.Continent)
                        .SetOrderByExpression(p => p.Metadata.Continent);

                        row.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                .SetNodeEditor(editor =>
                {
                    editor
                    // the Up button allows users to get one level up (based upon the tree)
                    .AddDefaultButton(DefaultButtonType.Up, "Back to list", "Back")
                    .AddDefaultButton(DefaultButtonType.SaveExisting)
                    .AddDefaultButton(DefaultButtonType.SaveNew)
                    .AddDefaultButton(DefaultButtonType.Delete)

                    // using navigation buttons can help the user to other pages quickly
                    .AddNavigationButton <NavigateToPersonHandler>("Create new person", "FollowUser", isVisible: (country, state) => state == EntityState.IsExisting);

                    editor.AddSection(section =>
                    {
                        section.AddField(x => x.Name);

                        section.AddField(x => x.Metadata.Continent);
                        section.AddField(x => x.Metadata.Tag)
                        .SetType(EditorType.Dropdown)
                        // the FixedOptionsDataProvider allows for adding hard-coded options, without requiring a Enum
                        .SetDataCollection(new FixedOptionsDataProvider(
                                               new[]
                        {
                            "Tag A",
                            "Tag B",
                            "Tab C"
                        }));

                        // this property contains a list of people it is related to
                        // you can see it as a ICollection<TRelated> property in EF Core

                        // because this property has an RelationValidationAttribute, the CMS first checks if the
                        // selected values are valid, before allowing the user to save this entity.
                        // in this example, the user may only select up to two People per Country

                        section.AddField(x => x.People)
                        // a multi-select is a list of checkboxes
                        .SetType(EditorType.MultiSelect)
                        // this binds the PersonCollection to this collection
                        // the CMS must know what the foreign entity and key is, you need to specify it
                        .SetCollectionRelation <Person, int>(
                            // this selects which values are used as selected values
                            people => people.Select(p => p.Id),
                            // alias of the related collection
                            "person",
                            // this callback allows you to specify how the multi-select should look like
                            relation =>
                        {
                            relation
                            // when the user selects an element, the value that is used as Id is used
                            // to set the value of the property
                            .SetElementIdProperty(x => x.Id)

                            // multiple display properties can be used to display the dropdown, even
                            // with nested properties
                            .SetElementDisplayProperties(x => x.Name, x => x.Details.Email);
                        });
                    });

                    editor.AddSection(section =>
                    {
                        section.SetLabel("Related people");

                        section.AddRelatedCollectionList <Person, BaseRepository <Person> >(relation =>
                        {
                            relation.SetListEditor(editor =>
                            {
                                editor.AddDefaultButton(DefaultButtonType.Return);
                                editor.AddDefaultButton(DefaultButtonType.Add);
                                editor.AddDefaultButton(DefaultButtonType.New);

                                editor.AddSection(row =>
                                {
                                    row.AddField(x => x.Name);

                                    row.AddDefaultButton(DefaultButtonType.Pick);
                                    row.AddDefaultButton(DefaultButtonType.Remove);
                                    row.AddDefaultButton(DefaultButtonType.SaveExisting);
                                    row.AddDefaultButton(DefaultButtonType.SaveNew);
                                    row.AddDefaultButton(DefaultButtonType.Delete);
                                });
                            });
                        });
                    });
                });
            });
        }
Ejemplo n.º 19
0
        public static void AddTagCollection(this ICmsConfig config)
        {
            config.AddCollection <TagGroup, JsonRepository <TagGroup> >("taggroup", "Tag groups", collection =>
            {
                collection
                .SetTreeView(EntityVisibilty.Hidden, x => x.Name)
                .SetListEditor(editor =>
                {
                    editor.SetListType(ListType.Block);

                    editor.SetSearchBarVisibility(false);

                    editor.AddDefaultButton(DefaultButtonType.Return);
                    editor.AddDefaultButton(DefaultButtonType.New);

                    editor
                    .AddSection(section =>
                    {
                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);

                        section.AddField(x => x.Name);

                        section.AddField(x => x.DefaultTagId).SetName("Default tag")
                        .SetType(EditorType.Dropdown)
                        .SetCollectionRelation <Tag, JsonRepository <Tag> >(config =>
                        {
                            // this allows for configuring which property of the entity will make up the id for the element, and that value
                            // is set to FavouriteChildId when the user selects an element
                            config.SetElementIdProperty(x => x.Id);

                            // because a single label is often not enough, you can add more properties to make the labels for each option
                            config.SetElementDisplayProperties(x => x.Name, x => $"{x.Id} - {x.Name}");

                            // sets the entity that is currently edited as parent for the repository to get elements for this field
                            config.SetEntityAsParent();

                            // the data in this dropdown will refresh automatically when the repository on which the data
                            // is based flags that the data has been updated
                        });

                        // it is possible to view or edit an subcollection from the parent
                        // when adding a subcollection in an Editor will have to be a ListEditor while
                        // adding a subcollection in a View will be a ListView.

                        // the entity of this editor will be passed in as IParent in the repository of the
                        // sub collection, making it possible to access the parents properties in the childrens repository
                        section.AddSubCollectionList <Tag, JsonRepository <Tag> >(config =>
                        {
                            config.SetListEditor(editor =>
                            {
                                editor.SetSearchBarVisibility(false);

                                editor.AddDefaultButton(DefaultButtonType.Return);
                                editor.AddDefaultButton(DefaultButtonType.New);

                                editor.AddSection(section =>
                                {
                                    section.AddDefaultButton(DefaultButtonType.SaveExisting);
                                    section.AddDefaultButton(DefaultButtonType.SaveNew);

                                    // add custom buttons and action handlers using the following handler
                                    section.AddCustomButton <RandomNameActionHandler>(typeof(CustomButton), "Create name", "add-circle");

                                    section.AddField(x => x.Name);
                                });
                            });
                        });

                        // if you want to reuse a collection in multiple views, you can also reference it by alias
                        // if you comment out the AddSubCollectionList above this comment, and enable the AddSubCollectionList below,
                        // the editor will work identical, but now the collection with alias "tag" can be used for multiple things

                        // section.AddSubCollectionList("tag");
                    });
                });

                // any collection can be added as subcollection, even collections based upon totally difference repositories
                // this lets you mix repositories which are based upon totally different databases easily
                collection
                .AddSubCollection <Tag, JsonRepository <Tag> >("tag", "Tags", subCollection =>
                {
                    subCollection
                    .SetListEditor(editor =>
                    {
                        editor.SetListType(ListType.Table);

                        editor.SetSearchBarVisibility(false);

                        editor.AddDefaultButton(DefaultButtonType.Return);
                        editor.AddDefaultButton(DefaultButtonType.New);
                        editor.AddDefaultButton(DefaultButtonType.SaveExisting);

                        editor.AddSection(section =>
                        {
                            section.AddDefaultButton(DefaultButtonType.SaveExisting);
                            section.AddDefaultButton(DefaultButtonType.SaveNew);

                            // add custom buttons and action handlers using the following handler
                            section.AddCustomButton <RandomNameActionHandler>(typeof(CustomButton), "Create name", "add-circle");

                            section.AddField(x => x.Name);
                        });
                    });
                });
            });
        }
Ejemplo n.º 20
0
        public static void AddTagCollection(this ICmsConfig config)
        {
            config.AddCollection <TagGroup>("taggroup", "Tag groups", collection =>
            {
                collection
                .SetTreeView(EntityVisibilty.Hidden, x => x.Name)
                .SetRepository <JsonRepository <TagGroup> >()
                .SetListEditor(ListType.Block, editor =>
                {
                    editor.SetSearchBarVisibility(false);

                    editor.AddDefaultButton(DefaultButtonType.Return);
                    editor.AddDefaultButton(DefaultButtonType.New);

                    editor
                    .AddSection(section =>
                    {
                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);

                        section.AddField(x => x.Name);

                        // it is possible to view or edit an subcollection from the parent
                        // when adding a subcollection in an Editor will render the ListEditor while
                        // adding a subcollection in a View will render the ListView.

                        // the entity of this editor will be passed in as IParent in the repository of the
                        // sub collection, making it possible to access the parents properties in the childrens repository

                        section.AddSubCollectionList <Tag>("tag");
                    });
                });

                // any collection can be added as subcollection, even collections based upon totally difference repositories
                // this lets you mix repositories which are based upon totally different databases easily
                collection
                .AddCollection <Tag>("tag", "Tags", subCollection =>
                {
                    subCollection
                    .SetRepository <JsonRepository <Tag> >()
                    .SetListEditor(ListType.Table, editor =>
                    {
                        editor.SetSearchBarVisibility(false);

                        editor.AddDefaultButton(DefaultButtonType.Return);
                        editor.AddDefaultButton(DefaultButtonType.New);

                        editor.AddSection(section =>
                        {
                            section.AddDefaultButton(DefaultButtonType.SaveExisting);
                            section.AddDefaultButton(DefaultButtonType.SaveNew);

                            // add custom buttons and action handlers using the following handler
                            section.AddCustomButton <RandomNameActionHandler>(typeof(CustomButton), "Create name", "add-circle");

                            section.AddField(x => x.Name);
                        });
                    });
                });
            });
        }
Ejemplo n.º 21
0
        // CRUD editor for simple POCO with recursive sub collections
        public static void AddPersonCollection(this ICmsConfig config)
        {
            config.AddCollection <Person>("person", "People", collection =>
            {
                collection
                .SetTreeView(x => x.Name)
                // this repository handles all the CRUD for this collection
                .SetRepository <JsonRepository <Person> >()
                // a list view is a table that displays a row (or multiple rows) of info per entity
                .SetListView(view =>
                {
                    // if new entities can be made using the CMS, include a New button so users can insert new entities
                    view.AddDefaultButton(DefaultButtonType.New);

                    // multiple rows can be added to display even more data
                    // only the first row will be used to generate headers
                    view.AddRow(row =>
                    {
                        // views always require you to specify strings, so the Id (an int) must be .ToString-ed.
                        // since this messes up the name of the column, you can set it to a nice name
                        row.AddField(p => p.Id.ToString()).SetName("ID");
                        row.AddField(p => p.Name);

                        // if an entity can be edited, include an Edit button so users can start editing entities
                        // the edit button in a list will always direct the user to the NodeEditor
                        row.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                // a list editor is similair to a list view, but every column contains an editor so multiple entities can be edited in one go
                // a list editor takes precedence over a list view, so when navigating to the Person collection, this view will be displayed
                .SetListEditor(editor =>
                {
                    // adding Up to the button bar allows the user to get to the level above the current page (base upon the tree)
                    // this button will be hidden automatically when the user is at the root
                    editor.AddDefaultButton(DefaultButtonType.Up);

                    // in a list editor a New allows the user to add entities, within the list editor
                    editor.AddDefaultButton(DefaultButtonType.New);
                    editor.AddDefaultButton(DefaultButtonType.Return);

                    // a list editor can be in the shape of a table, or a set of blocks, so these sections are either rows or blocks
                    editor.AddSection(row =>
                    {
                        // these fields will be the editors
                        row.AddField(p => p.Id).SetType(EditorType.Readonly);
                        row.AddField(p => p.Name);

                        // the SaveExisting button is only displayed when an entity is edited
                        row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true);
                        // the SaveNew button is only displayed when an entity is inserted
                        row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true);

                        // the View button always directs the user to the NodeView
                        row.AddDefaultButton(DefaultButtonType.View);
                        // the Edit button always directs the user to the NodeEdit
                        row.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                .SetNodeEditor(editor =>
                {
                    // adding Up to the button bar allows the user to get to the level above the current page (base upon the tree)
                    editor.AddDefaultButton(DefaultButtonType.Up);

                    // just as in the ListEditor, SaveExisting only shows when the user is editing an existing entity,
                    // and the SaveNew only when inserting an entity
                    editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true);
                    editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true);

                    // if an entity can be deleted, add a button for it, so the user can delete the entity
                    editor.AddDefaultButton(DefaultButtonType.Delete);

                    // an node editor can have multiple sections, which are displayed as seperte blocks
                    editor.AddSection(section =>
                    {
                        // the DisableWhen expression is evaluated everytime any property of the entity is updated
                        // so this allows you to make response forms which show or hide parts based upon the entity and its state
                        section.AddField(x => x.Id).DisableWhen((person, state) => true);

                        // it is allowed to use DisplayType fields in Editors, so some readonly data can easily be displayed
                        section.AddField(x => x.Name).SetType(DisplayType.Label);
                        section.AddField(x => x.Email);
                    });

                    // you can even have sections specifically for an entity type.
                    // if the repository can return multiple types of entities (all derived from a shared base type),
                    // sections can be made specifically for a type
                    editor.AddSection <Person>(section =>
                    {
                        // sections can have labels to make complex forms more understandable
                        section.SetLabel("Biography");

                        // sections can be hidden using VisibleWhen, based upon the entity or the state of that entity
                        // so users won't be confronted with editors that do not apply
                        section.VisibleWhen((person, state) => state == EntityState.IsExisting);

                        // there are many types of editors available, and even custom types can be used
                        section.AddField(x => x.Bio).SetType(EditorType.TextArea);
                    });

                    editor.AddSection(section =>
                    {
                        // relations with other entities, collections and repositories are first-class in RapidCMS
                        // so this field will allow the user to select an entity that is one level deeper in the person-tree
                        section.AddField(x => x.FavouriteChildId)
                        .SetName("Favourite child")
                        .SetType(EditorType.Select)
                        .SetCollectionRelation <Person>("person", config =>
                        {
                            // this allows for configuring which property of the entity will make up the id for the element, and that value
                            // is set to FavouriteChildId when the user selects an element
                            config.SetElementIdProperty(x => x.Id);

                            // because a single label is often not enough, you can add more properties to make the labels for each option
                            config.SetElementDisplayProperties(x => x.Name, x => $"{x.Id} - {x.Email}");

                            // sets the entity that is currently edited as parent for the repository to get elements for this field
                            config.SetEntityAsParent();

                            // any level from the tree can be picked:
                            // Favouite sibling: config.SetRepositoryParent(x => x);
                            // Favouite parent: config.SetRepositoryParent(x => x.Parent);
                            // Favouite grand parent: config.SetRepositoryParent(x => x.Parent != null ? x.Parent.Parent : default); // ?. is not yet supported in expressions..
                        });
                    });
                })
                .SetNodeView(view =>
                {
                    view.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true);
                    view.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true);

                    view.AddDefaultButton(DefaultButtonType.Delete);

                    view.AddSection(section =>
                    {
                        // views also allow for customization of how the data should be displayed
                        // you can use the availablep DisplayType's, or create your own Razor components (must be derived from BaseDisplay)
                        section.AddField(x => x.Id.ToString()).SetName("ID").SetType(DisplayType.Pre);
                        section.AddField(x => x.Name).SetType(DisplayType.Label);
                        section.AddField(x => x.Email).SetType(typeof(EmailDisplay));
                    });

                    view.AddSection(section =>
                    {
                        section.AddField(x => x.Bio);
                    });
                });

                collection.AddSelfAsRecursiveCollection();
            });
        }
Ejemplo n.º 22
0
        // CRUD editor for simple POCO with recursive sub collections
        public static void AddPersonCollection(this ICmsConfig config)
        {
            config.AddCollection <Person, BaseRepository <Person> >("person", "Contact", "Red20", "People", collection =>
            {
                collection
                .SetTreeView(x => x.Name)
                .SetElementConfiguration(
                    x => x.Id,
                    x => x.Name,
                    x => x.Details != null ? x.Details.Email : "")
                // this repository handles all the CRUD for this collection
                // a list view is a table that displays a row (or multiple rows) of info per entity
                .SetListView(view =>
                {
                    // if new entities can be made using the CMS, include a New button so users can insert new entities
                    view.AddDefaultButton(DefaultButtonType.New);

                    // multiple rows can be added to display even more data
                    // only the first row will be used to generate headers
                    view.AddRow(row =>
                    {
                        // views always require you to specify strings, so the Id (an int) must be .ToString-ed.
                        // since this messes up the name of the column, you can set it to a nice name
                        row.AddField(p => p.Id.ToString()).SetName("ID");
                        row.AddField(p => p.Name);

                        // if an entity can be edited, include an Edit button so users can start editing entities
                        // the edit button in a list will always direct the user to the NodeEditor
                        row.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                // a list editor is similar to a list view, but every column contains an editor so multiple entities can be edited in one go
                // a list editor takes precedence over a list view, so when navigating to the Person collection, this view will be displayed
                .SetListEditor(editor =>
                {
                    editor.SetPageSize(20);

                    // adding Up to the button bar allows the user to get to the level above the current page (base upon the tree)
                    // this button will be hidden automatically when the user is at the root
                    editor.AddDefaultButton(DefaultButtonType.Up);

                    // in a list editor a New allows the user to add entities, within the list editor
                    editor.AddDefaultButton(DefaultButtonType.New);
                    editor.AddDefaultButton(DefaultButtonType.Return);

                    // adding a SaveExisting button to the ListEditor allows the user to bulk-save the entire list
                    // (only modified entities are touched)
                    editor.AddDefaultButton(DefaultButtonType.SaveExisting);

                    // allowing reordering so the user can shuffle the entities around and save them in a new order.
                    // the Repository must implement ReorderAsync
                    editor.AllowReordering(true);

                    // a list editor can be in the shape of a table, or a set of blocks, so these sections are either rows or blocks
                    editor.AddSection(row =>
                    {
                        // these fields will be the editors
                        row.AddField(p => p.Id).SetType(EditorType.Readonly);
                        row.AddField(p => p.Name);

                        // the SaveExisting button is only displayed when an entity is edited
                        row.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true);
                        // the SaveNew button is only displayed when an entity is inserted
                        row.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true);

                        // the View button always directs the user to the NodeView
                        row.AddDefaultButton(DefaultButtonType.View);
                        // the Edit button always directs the user to the NodeEdit
                        row.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                .SetNodeEditor(editor =>
                {
                    // adding Up to the button bar allows the user to get to the level above the current page (base upon the tree)
                    editor.AddDefaultButton(DefaultButtonType.Up);

                    // just as in the ListEditor, SaveExisting only shows when the user is editing an existing entity,
                    // and the SaveNew only when inserting an entity
                    editor.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true);
                    editor.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true);

                    // if an entity can be deleted, add a button for it, so the user can delete the entity
                    editor.AddDefaultButton(DefaultButtonType.Delete);

                    // an node editor can have multiple sections, which are displayed as separate blocks
                    editor.AddSection(section =>
                    {
                        // the DisableWhen expression is evaluated every time any property of the entity is updated
                        // so this allows you to make response forms which show or hide parts based upon the entity and its state
                        section.AddField(x => x.Id).DisableWhen((person, state) => true);

                        // it is allowed to use DisplayType fields in Editors, so some read only data can easily be displayed
                        section.AddField(x => x.Name);     //.SetType(DisplayType.Label);

                        // if properties are in nested objects (like owned entities in EF), the editors support those as well
                        // flagging such property with [ValidateObject] will have the nested object validated as well
                        section.AddField(x => x.Details.Email)
                        // by default, all the properties will be combined to form the Name of the property (DetailsEmail in this example)
                        // so using SetName this can be set to something more user friendly
                        .SetName("Email")
                        .SetDetails(new MarkupString("<p>An email adress looks like <code>[email protected]</code>.</p>"));
                    });

                    // you can even have sections specifically for an entity type.
                    // if the repository can return multiple types of entities (all derived from a shared base type),
                    // sections can be made specifically for a type
                    editor.AddSection <Person>(section =>
                    {
                        // sections can have labels to make complex forms more understandable
                        section.SetLabel("Biography");

                        // sections can be hidden using VisibleWhen, based upon the entity or the state of that entity
                        // so users won't be confronted with editors that do not apply
                        section.VisibleWhen((person, state) => state == EntityState.IsExisting);

                        // there are many types of editors available, and even custom types can be used
                        section.AddField(x => x.Details.Bio).SetType(EditorType.TextArea).SetName("Bio");
                    });

                    editor.AddSection(section =>
                    {
                        // relations with other entities, collections and repositories are first-class in RapidCMS
                        // so this field will allow the user to select an entity that is one level deeper in the person-tree
                        section.AddField(x => x.FavouriteChildId)
                        .SetName("Favorite child")
                        .SetType(EditorType.Select)
                        .VisibleWhen((person, state) => state == EntityState.IsExisting)
                        .SetCollectionRelation <Person>("person", config =>
                        {
                            // this allows for configuring which property of the entity will make up the id for the element, and that value
                            // is set to FavouriteChildId when the user selects an element
                            config.SetElementIdProperty(x => x.Id);

                            // because a single label is often not enough, you can add more properties to make the labels for each option
                            config.SetElementDisplayProperties(x => x.Name, x => $"{x.Id} - {x.Details.Email}");

                            // sets the entity that is currently edited as parent for the repository to get elements for this field
                            config.SetEntityAsParent();

                            // any level from the tree can be picked:
                            // Favorite sibling: config.SetRepositoryParent(x => x);
                            // Favorite parent: config.SetRepositoryParent(x => x.Parent);
                            // Favorite grand parent: config.SetRepositoryParent(x => x.Parent != null ? x.Parent.Parent : default); // ?. is not yet supported in expressions..
                        });
                    });

                    // add the sub collection as element to the node editor
                    editor.AddSection(section =>
                    {
                        section.AddSubCollectionList("person");
                    });
                })
                .SetNodeView(view =>
                {
                    view.AddDefaultButton(DefaultButtonType.SaveExisting, isPrimary: true);
                    view.AddDefaultButton(DefaultButtonType.SaveNew, isPrimary: true);

                    view.AddDefaultButton(DefaultButtonType.Delete);

                    view.AddSection(section =>
                    {
                        // views also allow for customization of how the data should be displayed
                        // you can use the available DisplayType's, or create your own Razor components (must be derived from BaseDisplay)
                        section.AddField(x => x.Id.ToString()).SetName("ID").SetType(DisplayType.Pre);
                        section.AddField(x => x.Name).SetType(DisplayType.Label);
                        section.AddField(x => x.Details.Email).SetType(typeof(EmailDisplay));
                    });

                    view.AddSection(section =>
                    {
                        section.AddField(x => x.Details.Bio);
                    });
                });

                collection.AddSelfAsRecursiveCollection();

                // if the regular node editor of an entity is getting too cluttered, or if you want to move some of the functionality
                // to a separate page, a detail page can be quite useful.
                // a detail page is always a NodeEditor, and is only visible on existing entity.
                // the repository it fetches its data from can have its own entity type, but the ID that is used to query for the data
                // is the same as the entity the page is part of.
                // it is also possible to create a navigation button to navigate to a details page, by building a INavigationHandler that
                // calls NavigationRequest.NavigateToDetails (see NavigateToPersonHandler)
                collection.AddDetailPage <Details, BaseRepository <Details> >("person-details", "Settings", "Red20", "Details", config =>
                {
                    config.AddDefaultButton(DefaultButtonType.SaveExisting, "Save");

                    config.AddSection(section =>
                    {
                        section.AddField(x => x.Title);
                        section.AddField(x => x.History);

                        // when a model has a sub class which has a few simple properties, it's possible to group those properties
                        // into a single editor using the ModelEditor type. this editor uses the same rules as the convention based
                        // approach (see ConventionCollection), but groups the editors together of this property.
                        //
                        // to validate the properties of the nested object, the Nested property must be attributed with [ValidateObjectAsProperty]
                        // to instruct the data annotation validator to validate NestedDetails and use that validation as validation result
                        // for Nested.
                        section.AddField(x => x.Nested)
                        .SetType(EditorType.ModelEditor);
                    });
                });
            });
        }
Ejemplo n.º 23
0
 public TreeElementsSetupResolver(ICmsConfig cmsConfig,
                                  ISetupResolver <IEnumerable <ITreeElementSetup>, IEnumerable <ITreeElementConfig> > treeElementResolver)
 {
     _cmsConfig           = cmsConfig;
     _treeElementResolver = treeElementResolver;
 }
Ejemplo n.º 24
0
        // CRUD editor with support for
        public static void AddEntityVariantCollection(this ICmsConfig config)
        {
            config.AddCollection <EntityVariantBase, BaseRepository <EntityVariantBase> >("variants", "ProductVariant", "OrangeYellow20", "Entity Variants", collection =>
            {
                collection
                // Set showEntities to true to have this collection to fold open on default
                .SetTreeView(x => x.Name, showEntitiesOnStartup: true)

                // entity variants must be based of the same base type, but can introduce form elements for specialised cases
                .AddEntityVariant <EntityVariantA>("Variant A", "a")
                .AddEntityVariant <EntityVariantB>("Variant B", "b")
                .AddEntityVariant <EntityVariantC>("Variant C", "c")
                .SetListEditor(view =>
                {
                    view.AddDefaultButton(DefaultButtonType.New, label: "New {0}");
                    view.AddDefaultButton(DefaultButtonType.Return);

                    view.SetColumnVisibility(EmptyVariantColumnVisibility.Visible);

                    view.SetPageSize(10);

                    view
                    .AddSection(section =>
                    {
                        section.AddField(p => p.Id);

                        section.AddField(p => p.Name)
                        .SetOrderByExpression(p => p.Name, OrderByType.Ascending);
                    })
                    .AddSection <EntityVariantA>(section =>
                    {
                        section.AddField(p => p.Id);

                        section.AddField(p => p.Name)
                        .SetOrderByExpression(p => p.Name, OrderByType.Ascending);

                        section.AddField(p => p.NameA1);

                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);
                        section.AddDefaultButton(DefaultButtonType.Edit);
                    });

                    view
                    .AddSection <EntityVariantB>(section =>
                    {
                        section.AddField(p => p.Id);

                        section.AddField(p => p.Name)
                        .SetOrderByExpression(p => p.Name, OrderByType.Ascending);

                        section.AddField(p => p.NameB1);
                        section.AddField(p => p.NameB2);

                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);
                        section.AddDefaultButton(DefaultButtonType.Edit);
                    });

                    view
                    .AddSection <EntityVariantC>(section =>
                    {
                        section.AddField(p => p.Id);

                        section.AddField(p => p.Name)
                        .SetOrderByExpression(p => p.Name, OrderByType.Ascending);

                        section.AddField(p => p.NameC1);
                        section.AddField(p => p.NameC2);
                        section.AddField(p => p.NameC3);

                        section.AddDefaultButton(DefaultButtonType.SaveExisting);
                        section.AddDefaultButton(DefaultButtonType.SaveNew);
                        section.AddDefaultButton(DefaultButtonType.Edit);
                    });
                })
                .SetNodeEditor(editor =>
                {
                    editor.AddDefaultButton(DefaultButtonType.Up);
                    editor.AddDefaultButton(DefaultButtonType.SaveNew);
                    editor.AddDefaultButton(DefaultButtonType.SaveExisting);

                    editor.AddSection(generic =>
                    {
                        generic.SetLabel("Generics");

                        generic.AddField(x => x.Id).SetType(DisplayType.Pre);
                        generic.AddField(x => x.Name);
                    });

                    editor.AddSection <EntityVariantA>(a =>
                    {
                        a.SetLabel("Variant A specifics");

                        a.AddField(x => x.NameA1);
                    });

                    editor.AddSection <EntityVariantB>(b =>
                    {
                        b.SetLabel("Variant B specifics");

                        b.AddField(x => x.NameB1);
                        b.AddField(x => x.NameB2);
                    });

                    editor.AddSection <EntityVariantC>(c =>
                    {
                        c.SetLabel("Variant C specifics");

                        c.AddField(x => x.NameC1);
                        c.AddField(x => x.NameC2);
                        c.AddField(x => x.NameC3);
                    });
                });
            });
        }
Ejemplo n.º 25
0
        /// <summary>
        /// This method adds the Model Maker plugin to RapidCMS without the Model collection.
        ///
        /// Use this when the code runs in production.
        /// </summary>
        /// <param name="cmsConfig"></param>
        /// <returns></returns>
        public static ICmsConfig AddModelMakerPluginCore(this ICmsConfig cmsConfig)
        {
            cmsConfig.AddPlugin <ModelMakerPlugin>();

            return(cmsConfig);
        }