Beispiel #1
0
        public override IPackage Build(IFluentBuilder fluentBuilder)
        {
            // This is an example of how to define a new region that is like an
            // existing one but with a different name and has different properties.
            //
            // The new region will be registered with the fluent builder and its name
            // will be resolvable by other elements in the solution.
            //
            // This technique will work for any of the RegionExample1..RegionExample4
            // above, but will not work for RegionExample5
            fluentBuilder.BuildUpRegion(new RegionExample2(Dependencies.RegionDependenciesFactory))
            .Name("region2a")
            .BindTo <NewsItem>("breaking-news")
            .ClassNames("news", "breaking")
            .Build();

            // This is an example of how you can construct and register a fully custom
            // implementation of IRegion with the fluent builder
            var regionExample5 = new RegionExample5() as IRegion;

            regionExample5.Name = "region5";
            fluentBuilder.Register(regionExample5);

            return(this);
        }
        public override IPackage Build(IFluentBuilder builder)
        {
            // This "div" region outputs a <div> container
            var divRegion = builder.BuildUpRegion()
                            .Name("div")
                            .Tag("div")
                            .Build();

            // This "null" region outputs no markup
            var nullRegion = builder.BuildUpRegion()
                             .Name("null")
                             .Tag("")
                             .Build();

            // The "full_page" layout has a single region
            var fullPageLayout = builder.BuildUpLayout()
                                 .Name("full_page")
                                 .Tag("div")
                                 .ClassNames("{ns}_ly_full_page")
                                 .DeployCss("div.{ns}_ly_full_page", "height:auto; width:auto; overflow-x: hidden; overflow-y: auto;")
                                 .ZoneNesting("main")
                                 .Region("main", nullRegion)
                                 .Build();

            // The "col_2_left_fixed" layout has two columns where the left column
            // has a fixed with. Specify the width using your application CSS
            var twoColumnFixedLeftLayout = builder.BuildUpLayout()
                                           .Name("col_2_left_fixed")
                                           .Tag("div")
                                           .ClassNames("{ns}_ly_col_2_left_fixed")
                                           .DeployCss("div.{ns}_ly_col_2_left_fixed", "overflow: hidden;")
                                           .DeployCss("div.{ns}_ly_col_2_left_fixed > div.{ns}_rg_col_left", "overflow: hidden; float: left; width: 250px;")
                                           .DeployCss("div.{ns}_ly_col_2_left_fixed > div.{ns}_rg_col_right", "margin-left: 250px;")
                                           .ZoneNesting("left,right")
                                           .Region("left",
                                                   builder.BuildUpRegion()
                                                   .Tag("div")
                                                   .ClassNames("{ns}_rg_col_left")
                                                   .Build())
                                           .Region("right",
                                                   builder.BuildUpRegion()
                                                   .Tag("div")
                                                   .ClassNames("{ns}_rg_col_right")
                                                   .Build())
                                           .Build();

            // The "col_2_right_fixed" layout has two columns where the right column
            // has a fixed with. Specify the width using your application CSS
            var twoColumnFixedRightLayout = builder.BuildUpLayout()
                                            .Name("col_2_right_fixed")
                                            .Tag("div")
                                            .ClassNames("{ns}_ly_col_2_right_fixed")
                                            .DeployCss("div.{ns}_ly_col_2_right_fixed", "overflow: hidden;")
                                            .DeployCss("div.{ns}_ly_col_2_right_fixed > div.{ns}_rg_col_left", "overflow: hidden; width: auto;")
                                            .DeployCss("div.{ns}_ly_col_2_right_fixed > div.{ns}_rg_col_right", "width: 250px; float: right;")
                                            .ZoneNesting("right,left")
                                            .Region("left",
                                                    builder.BuildUpRegion()
                                                    .Tag("div")
                                                    .ClassNames("{ns}_rg_col_left")
                                                    .Build())
                                            .Region("right",
                                                    builder.BuildUpRegion()
                                                    .Tag("div")
                                                    .ClassNames("{ns}_rg_col_right")
                                                    .Build())
                                            .Build();

            return(this);
        }
Beispiel #3
0
        private IRegion BuildRegion(
            IFluentBuilder builder,
            long regionId)
        {
            long regionVersionId;

            if (!_regionVersions.TryGetValue(regionId, out regionVersionId))
            {
                throw new Exception("The website version does not define which version of region ID " + regionId + " to use");
            }

            var data          = _database.GetRegionVersion(regionVersionId, (l, v) => new Tuple <RegionRecord, RegionVersionRecord>(l, v));
            var region        = data.Item1;
            var regionVersion = data.Item2;

            regionVersion.VersionName = region.Name + "_v" + regionVersion.Version;

            var regionDefinition = builder.BuildUpRegion()
                                   .Name(regionVersion.VersionName)
                                   .AssetDeployment(regionVersion.AssetDeployment)
                                   .DeployIn(regionVersion.ModuleName);

            if (regionVersion.Components != null)
            {
                foreach (var component in regionVersion.Components)
                {
                    regionDefinition.NeedsComponent(component.ComponentName);
                }
            }

            var hasLayout = false;

            if (regionVersion.LayoutId.HasValue)
            {
                regionDefinition.Layout(GetLayout(builder, regionVersion.LayoutId.Value));
                hasLayout = true;
            }
            else if (!string.IsNullOrEmpty(regionVersion.LayoutName))
            {
                regionDefinition.Layout(regionVersion.LayoutName);
                hasLayout = true;
            }
            else if (regionVersion.ComponentId.HasValue)
            {
                long componentVersionId;
                if (!_componentVersions.TryGetValue(regionVersion.ComponentId.Value, out componentVersionId))
                {
                    throw new Exception("zone version ID " + regionVersion.RecordId +
                                        " references component ID " + regionVersion.ComponentId.Value +
                                        " but this component has no version defined for this version of the website");
                }

                var componentRecord = _database.GetComponentVersion(componentVersionId, (c, v) => c);
                var componentName   = componentRecord.Name;

                var regionProperties = _database.GetElementPropertyValues(regionVersion.RecordId);
                if (regionProperties != null && regionProperties.Count > 0)
                {
                    _dependencies.NameManager.AddResolutionHandler(
                        NameResolutionPhase.ResolveElementReferences,
                        nm =>
                    {
                        var component = nm.ResolveComponent(componentName, this);
                        var cloneable = component as ICloneable;

                        if (cloneable != null)
                        {
                            component = (IComponent)cloneable.Clone();
                            var componentProperties = component.GetType().GetProperties();
                            foreach (var regionProperty in regionProperties)
                            {
                                var componentProperty = componentProperties.FirstOrDefault(
                                    p => string.Equals(p.Name, regionProperty.Key, StringComparison.OrdinalIgnoreCase));
                                if (componentProperty != null)
                                {
                                    componentProperty.SetValue(component, regionProperty.Value, null);
                                }
                            }
                        }
                        regionDefinition.Component(component);
                    });
                }
                else
                {
                    regionDefinition.Component(componentName);
                }
            }
            else if (!string.IsNullOrEmpty(regionVersion.AssetName))
            {
                regionDefinition.Html(regionVersion.AssetName, regionVersion.AssetValue);
            }
            else if (!string.IsNullOrEmpty(regionVersion.ComponentName))
            {
                regionDefinition.Component(regionVersion.ComponentName);
            }
            else if (regionVersion.RegionTemplates != null)
            {
                foreach (var template in regionVersion.RegionTemplates)
                {
                    regionDefinition.AddTemplate(template.TemplatePath, template.PageArea);
                }
            }

            if (regionVersion.DataScopes != null)
            {
                foreach (var dataScope in regionVersion.DataScopes)
                {
                    DataScopeRecord dataScopeRecord;
                    if (_dataScopes.TryGetValue(dataScope.DataScopeId, out dataScopeRecord))
                    {
                        if (dataScopeRecord.DataTypeId.HasValue)
                        {
                            DataTypeVersionRecord dataType;
                            if (!_dataTypes.TryGetValue(dataScopeRecord.DataTypeId.Value, out dataType))
                            {
                                throw new Exception("zone ID " + regionId +
                                                    " has an invalid data scope with ID " + dataScope.DataScopeId +
                                                    ". There is no data type ID " + dataScopeRecord.DataTypeId.Value +
                                                    " in this version of the website");
                            }

                            regionDefinition.DataScope(dataType.Type, dataScopeRecord.Name);
                        }
                        else
                        {
                            regionDefinition.DataProvider(dataScopeRecord.Name);
                        }
                    }
                }
            }

            if (regionVersion.RepeatDataTypeId.HasValue)
            {
                DataTypeVersionRecord dataType;
                if (!_dataTypes.TryGetValue(regionVersion.RepeatDataTypeId.Value, out dataType))
                {
                    throw new Exception("zone ID " + regionId +
                                        " has an invalid data repetition. There is no data type ID " + regionVersion.RepeatDataTypeId.Value +
                                        " in this version of the website");
                }

                var repeatScope = regionVersion.RepeatDataScopeName;
                var listScope   = regionVersion.ListDataScopeName;

                if (regionVersion.RepeatDataScopeId.HasValue)
                {
                    DataScopeRecord repeatScopeRecord;
                    if (_dataScopes.TryGetValue(regionVersion.RepeatDataScopeId.Value, out repeatScopeRecord))
                    {
                        repeatScope = repeatScopeRecord.Name;
                    }
                }

                if (regionVersion.ListDataScopeId.HasValue)
                {
                    DataScopeRecord listScopeRecord;
                    if (_dataScopes.TryGetValue(regionVersion.ListDataScopeId.Value, out listScopeRecord))
                    {
                        listScope = listScopeRecord.Name;
                    }
                }

                var childClasses = string.IsNullOrEmpty(regionVersion.ListElementClasses)
                    ? new string[0]
                    : regionVersion.ListElementClasses.Split(',');

                regionDefinition.ForEach(
                    dataType.Type,
                    repeatScope,
                    regionVersion.ListElementTag,
                    regionVersion.ListElementStyle,
                    listScope,
                    childClasses);
            }

            if (hasLayout && regionVersion.LayoutZones != null)
            {
                foreach (var zone in regionVersion.LayoutZones)
                {
                    if (zone.LayoutId.HasValue)
                    {
                        regionDefinition.Layout(GetLayout(builder, zone.LayoutId.Value));
                    }
                    else if (string.Equals(zone.ContentType, "html", StringComparison.OrdinalIgnoreCase))
                    {
                        regionDefinition.ZoneHtml(zone.ZoneName, zone.ContentName, zone.ContentValue);
                    }
                    else if (string.Equals(zone.ContentType, "layout", StringComparison.OrdinalIgnoreCase))
                    {
                        regionDefinition.ZoneLayout(zone.ZoneName, zone.ContentName);
                    }
                    else if (string.Equals(zone.ContentType, "template", StringComparison.OrdinalIgnoreCase))
                    {
                        regionDefinition.ZoneTemplate(zone.ZoneName, zone.ContentName);
                    }
                    else if (string.Equals(zone.ContentType, "component", StringComparison.OrdinalIgnoreCase))
                    {
                        regionDefinition.ZoneComponent(zone.ZoneName, zone.ContentName);
                    }
                }
            }

            return(regionDefinition.Build());
        }
        IPackage IPackage.Build(IFluentBuilder fluentBuilder)
        {
            // All CMS manager assets will be contained in a single module

            var module = fluentBuilder.BuildUpModule()
                         .Name("cms_manager")
                         .AssetDeployment(AssetDeployment.PerModule)
                         .Build();

            // Build the API services

            fluentBuilder.BuildUpService(null, typeof(LiveUpdateService))
            .Name("liveUpdate")
            .Route(_configuration.ServiceBasePath + "live-update/", new [] { Method.Get, Method.Post, Method.Delete }, 0)
            .RequiredPermission(Permissions.View, false)
            .CreateComponent("liveUpdateClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(CrudService))
            .Name("crud")
            .Route(_configuration.ServiceBasePath + "crud/", new [] { Method.Get, Method.Post, Method.Put, Method.Delete }, 0)
            .CreateComponent("crudClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(ListService))
            .Name("list")
            .Route(_configuration.ServiceBasePath + "list/", new [] { Method.Get, Method.Post }, 0)
            .CreateComponent("listClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(VersionsService))
            .Name("versions")
            .Route(_configuration.ServiceBasePath + "versions/", new [] { Method.Get, Method.Post, Method.Put, Method.Delete }, 0)
            .CreateComponent("versionsClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(HistoryService))
            .Name("history")
            .Route(_configuration.ServiceBasePath + "history/", new [] { Method.Get }, 0)
            .CreateComponent("historyClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(SegmentTestingService))
            .Name("segmentTesting")
            .Route(_configuration.ServiceBasePath + "segment-testing/", new [] { Method.Get, Method.Post, Method.Put, Method.Delete }, 0)
            .CreateComponent("segmentTestingClient")
            .DeployIn(module)
            .Build();

            // Load templates and accumulate all of the CSS and JS assets

            var scriptModules = new List <string>();

            LoadScriptModule("updateNotifierModule", scriptModules);
            LoadScriptModule("dataModule", scriptModules);
            LoadScriptModule("validationModule", scriptModules);
            LoadScriptModule("viewsModule", scriptModules);
            LoadScriptModule("filtersModule", scriptModules);
            LoadScriptModule("genericComponentsModule", scriptModules);
            LoadScriptModule("displayOnlyComponentsModule", scriptModules);
            LoadScriptModule("fieldEditorComponentsModule", scriptModules);
            LoadScriptModule("elementEditorComponentsModule", scriptModules);

            // Load templates that are directly loaded into regions

            var less = new StringBuilder();

            var cmsManagerTemplatePath = AddTemplate("CmsManager", less, scriptModules);
            var debugToolsTemplatePath = AddTemplate("DebugTools", less, scriptModules);

            // Load Vue temlates that are dynamically constructed in JavaScript

            AddTemplate("EnvironmentSelector", less, scriptModules);
            AddTemplate("WebsiteVersionSelector", less, scriptModules);
            AddTemplate("UserSegmentSelector", less, scriptModules);
            AddTemplate("SegmentationScenarioSelector", less, scriptModules);
            AddTemplate("SegmentationTestSelector", less, scriptModules);
            AddTemplate("PageSelector", less, scriptModules);
            AddTemplate("LayoutSelector", less, scriptModules);
            AddTemplate("RegionSelector", less, scriptModules);
            AddTemplate("ComponentSelector", less, scriptModules);

            AddTemplate("UserSegmentDisplay", less, scriptModules);
            AddTemplate("ContextDisplay", less, scriptModules);

            AddTemplate("EnvironmentEditor", less, scriptModules);
            AddTemplate("WebsiteVersionEditor", less, scriptModules);
            AddTemplate("SegmentationScenarioEditor", less, scriptModules);
            AddTemplate("PageEditor", less, scriptModules);
            AddTemplate("LayoutEditor", less, scriptModules);
            AddTemplate("RegionEditor", less, scriptModules);
            AddTemplate("ComponentEditor", less, scriptModules);

            AddTemplate("UpdateNotifierLog", less, scriptModules);

            // Output JavaScript and CSS assets in a module

            var assetsComponentBuilder = fluentBuilder.BuildUpComponent(null)
                                         .Name("assets")
                                         .DeployIn(module)
                                         .RenderInitialization("cms-manager-init", "<script>ns." + NamespaceName + ".init();</script>")
                                         .DeployLess(less.ToString());

            foreach (var scriptModule in scriptModules)
            {
                assetsComponentBuilder.DeployScript(scriptModule);
            }

            var assetsComponent = assetsComponentBuilder.Build();

            // This region of the CMS manager is for editing pages of the website
            var editorRegion = Build(module, assetsComponent, fluentBuilder.BuildUpRegion()
                                     .Name("editor")
                                     .NeedsComponent("crudClient")
                                     .NeedsComponent("listClient")
                                     .NeedsComponent("versionsClient")
                                     .NeedsComponent("historyClient")
                                     .NeedsComponent("segmentTestingClient")
                                     .AddTemplate(cmsManagerTemplatePath));

            // This region of the CMS manager is for debug tools
            var toolsRegion = Build(module, assetsComponent, fluentBuilder.BuildUpRegion()
                                    .Name("tools")
                                    .AddTemplate(debugToolsTemplatePath));

            // To have the CMS manager fill the whole page make this the page layout
            var managerLayout = fluentBuilder.BuildUpLayout()
                                .Name("manager")
                                .ZoneNesting("editor,tools")
                                .Region("editor", editorRegion)
                                .Region("tools", toolsRegion)
                                .Build();

            // To have the CMS manager occupy a region of the page put this region
            // into a zone of the page layout
            var managerRegion = fluentBuilder.BuildUpRegion()
                                .Name("manager")
                                .Layout(managerLayout)
                                .Build();

            // If the ManagerPath is configured then add a page to the website that
            // contains the CMS manager
            if (!string.IsNullOrEmpty(_configuration.ManagerPath))
            {
                fluentBuilder.BuildUpPage()
                .Name("cmsManager")
                .Route(_configuration.ManagerPath, 0, Method.Get)
                .Layout(managerLayout)
                .Build();
            }

            return(this);
        }
        /// <summary>
        /// This is the method that builds all of the compnents, layouts and regions
        /// that make up the menu package
        /// </summary>
        public override IPackage Build(IFluentBuilder builder)
        {
            /******************************************************************
            *
            * These things are shared between the desktop and mobile menus
            *
            ******************************************************************/

            // This component outputs CSS that makes the menu work as a menu
            builder.BuildUpComponent(new MenuStyles())
            .Name("menuStyles")
            .Build();

            // This component outputs CSS that defines the menu appearence
            builder.BuildUpComponent(new MenuStyle1())
            .Name("menuStyle1")
            .NeedsComponent("menuStyles")
            .Build();

            // This component displays a main menu item
            var mainMenuItemComponent = builder.BuildUpComponent(
                new MenuItemComponent(Dependencies.ComponentDependenciesFactory))
                                        .BindTo <MenuItem>()
                                        .Build();

            // This component displays a submenu item
            var subMenuItemComponent = builder.BuildUpComponent(
                new MenuItemComponent(Dependencies.ComponentDependenciesFactory))
                                       .BindTo <MenuItem>("submenu")
                                       .Build();

            // This data provider extracts sub-menu items from the current menu item
            // using fluent syntax.
            var subMenuDataProvider = builder.BuildUpDataProvider()
                                      .BindTo <MenuItem>()
                                      .Provides <IList <MenuItem> >((rc, dc, d) =>
            {
                var menuItem = dc.Get <MenuItem>();
                dc.Set <IList <MenuItem> >(menuItem.SubMenu, "submenu");
            },
                                                                    "submenu")
                                      .Build();

            /******************************************************************
            *
            * These things are for the desktop menu only
            *
            ******************************************************************/

            // This region is a container for the options on the desktop menu
            var desktopMenuItemRegion = builder.BuildUpRegion()
                                        .BindTo <MenuItem>()
                                        .Tag("div")
                                        .Component(mainMenuItemComponent)
                                        .Build();

            // This region is a container for the desktop drop down menu items. It
            // renders one menu item component for each menu item in the sub-menu
            var desktopDropDownMenuRegion = builder.BuildUpRegion()
                                            .Tag("div")
                                            .ClassNames("{ns}_dt_dropdown")
                                            .ForEach <MenuItem>("submenu", null, null, "submenu")
                                            .Component(subMenuItemComponent)
                                            .Build();

            // This layout defines the desktop menu option and the sub-menu that
            // drops down when the main menu option is tapped or hovered
            var desktopOptionLayout = builder.BuildUpLayout()
                                      .Tag("li")
                                      .ClassNames("{ns}_dt_option")
                                      .ZoneNesting("head,submenu")
                                      .Region("head", desktopMenuItemRegion)
                                      .Region("submenu", desktopDropDownMenuRegion)
                                      .DataProvider(subMenuDataProvider)
                                      .Build();

            // This region is the whole desktop menu structure with top level menu
            // options and sub-menus beneath each option. This is the region you
            // need to add to a layout in your page to display a desktop menu.
            builder.BuildUpRegion()
            .Name("desktop_menu")
            .Tag("ul")
            .NeedsComponent("menuStyles")
            .ClassNames("{ns}_dt_menu")
            .ForEach <MenuItem>("", "", "", "desktop")
            .Layout(desktopOptionLayout)
            .Build();

            /******************************************************************
            *
            * These things are for the mobile menu only
            *
            ******************************************************************/

            // This component displays the hamburger button
            var mobileHamburgerButtonComponent = builder.BuildUpComponent(
                new HamburgerButtonComponent(Dependencies.ComponentDependenciesFactory))
                                                 .Build();

            // This component displays a main menu item
            var mobileHeaderComponent = builder.BuildUpComponent(
                new MobileHeaderComponent(Dependencies.ComponentDependenciesFactory))
                                        .BindTo <MenuItem>()
                                        .Build();

            // This region contains a top-level option on the mobile menu
            var mobileMenuHead = builder.BuildUpRegion()
                                 .Tag("")
                                 .Component(mobileHeaderComponent)
                                 .Build();

            // This region repeats for each sub-menu option on a mobile menu
            var mobileSubMenu = builder.BuildUpRegion()
                                .Tag("")
                                .Component(subMenuItemComponent)
                                .ForEach <MenuItem>("submenu", "li", null, "submenu", "{ns}_mb_option")
                                .Build();

            // This layout defines mobile menus as having a head followed by a list
            // of the sub-menu options
            var mobileMenuOptionLayout = builder.BuildUpLayout()
                                         .Tag("")
                                         .ZoneNesting("head,subMenu")
                                         .Region("head", mobileMenuHead)
                                         .Region("subMenu", mobileSubMenu)
                                         .DataProvider(subMenuDataProvider)
                                         .Build();

            // This region contains the hamburger button
            var mobileHamburgerRegion = builder.BuildUpRegion()
                                        .Tag("")
                                        .Component(mobileHamburgerButtonComponent)
                                        .Build();

            // This region contains the panel that slides out from the edge of the page
            var mobileSlideoutRegion = builder.BuildUpRegion()
                                       .Tag("ul")
                                       .ClassNames("{ns}_mb_slideout")
                                       .ForEach <MenuItem>("", "", "", "mobile")
                                       .Layout(mobileMenuOptionLayout)
                                       .Build();

            // This layout is the top-level container for the mobile menu. It defines
            // the mobile menu consisting of a hamburger button and a slide-out panel
            var mobileMenuLayout = builder.BuildUpLayout()
                                   .ZoneNesting("hamburger,slideout")
                                   .Region("hamburger", mobileHamburgerRegion)
                                   .Region("slideout", mobileSlideoutRegion)
                                   .Build();

            // This region is the whole mobile menu structure with a hamburger
            // button that opens and closes a slide-out sidebar menu. This is
            // the region you would add to your website to include a mobile menu
            builder.BuildUpRegion()
            .Name("mobile_menu")
            .NeedsComponent("menuStyles")
            .ClassNames("{ns}_mb_menu")
            .Layout(mobileMenuLayout)
            .Build();

            return(this);
        }