Understanding Advantage CSP Components

Front-end Components

Frontend Components

The frontend hierarchy in Advantage CSP follows a structured flow from the Masterpage/page level down to "Layouts" that consist of "zones" and further down to "Modules" that utilize a grid system to present content.

Advantage MasterPage (AdvantageMasterPage)

An optional ASP.NET MasterPage tailored for the Advantage CSP framework, inheriting from System.Web.UI.MasterPage. It facilitates easier integration with the framework and enhances interaction with AdvantagePageTemplates by extending the base functionality of ASP.NET's MasterPage. Member Properties: Includes properties like AdvantagePage, ConfigurationEngine, CSPNonce, CurrentDomain, and others, which provide essential context and configurations specific to the page being served.

Advantage Page Template (AdvantagePageTemplate)

An ASP.NET page that inherits from System.Web.UI.Page, designed to work within the Advantage CSP framework. It offers extended functionalities to interact smoothly with various components of AdvantageCSP, like site settings, module engine, navigation engine, and page content. Interactions: This includes interactions with site settings, configuration, modules, navigation, and page management, facilitating access to domain-specific settings, language preferences, navigation elements, and page content.

Advantage Page Template (AdvantagePageTemplate)

An ASP.NET page that inherits from System.Web.UI.Page, designed to work within the Advantage CSP framework.It offers extended functionalities to interact smoothly with various components of AdvantageCSP, like site settings, module engine, navigation engine, and page content.Interactions: This includes interactions with site settings, configuration, modules, navigation, and page management, facilitating access to domain-specific settings, language preferences, navigation elements, and page content.
 

Image

 

Hierarchical Structure


The text highlights a hierarchical flow from a high-level MasterPage or page level down to finer details. This structure is essential for organizing the front-end of a web application, ensuring that pages are assembled in a modular and manageable way.
Layouts and Zones: These serve as containers within pages that dictate how content is organized and displayed. Layouts define the overall arrangement of content and can contain multiple zones, which are specific areas where content can be placed.
Modules and Grid System: Modules are reusable components that display content within the confines of a zone. They leverage a grid system for layout, which allows for responsive design and ensures that content is well-organized and visually appealing across different screen sizes.
Key Features


The framework's design emphasizes modularity, flexibility, and ease of integration with existing ASP.NET projects.
By inheriting and extending core ASP.NET classes (System.Web.UI.MasterPage and System.Web.UI.Page), it provides a streamlined way to incorporate advanced features and custom functionalities tailored to the needs of the Advantage CSP environment.
Properties like CurrentDomain, CurrentLanguage, IsPreview, and ModuleEngine offer granular control over the rendering and behavior of pages, making it easier to create dynamic, multi-lingual, and customizable web applications.

 

Conclusion

The Advantage CSP framework offers a structured and efficient way to develop front-end components for ASP.NET applications, with a focus on modular design, easy integration, and enhanced functionality. By understanding and utilizing these components, developers can build more robust, flexible, and user-friendly web applications.

 

 

Advantage MasterPage

AdvantageMasterPage Documentation

Methods & Properties

The AdvantageMasterPage is an optional ASP.NET MasterPage that inherits from System.Web.UI.MasterPage. It is designed to facilitate integration with the Advantage CSP framework.

Overview

The AdvantageMasterPage serves as an optional ASP.NET MasterPage intended for use within the Advantage CSP framework. It extends the functionality provided by System.Web.UI.MasterPage to enhance interaction with AdvantagePageTemplates.

Member Properties

The AdvantageMasterPage includes the following member properties:

  • AdvantagePage: Gets the advantage page.
  • ConfigurationEngine: Gets the configuration engine.
  • CSPNonce:
  • CurrentDomain: Gets the current domain.
  • CurrentLanguage: Gets the current language.
  • IsPreview: Gets a value indicating whether this instance is in preview mode.
  • IsSearchAgent: Gets a value indicating whether this instance is a search agent.
  • LanguageAbreviation: Gets the language abbreviation.
  • ModuleEngine: Gets the module engine.
  • RenderMode: Gets the render mode.

Default Template Location

The default template location for AdvantageMasterPage is under your website's /Templates folder.

Advantage Page Template

AdvantagePageTemplate Documentation

Methods & Properties

The AdvantagePageTemplate is an ASP.NET page that inherits from System.Web.UI.Page. It is designed to interact with the AdvantageCSP framework, providing seamless integration with various components.

Overview

The AdvantagePageTemplate serves as an ASP.NET page intended for use within the AdvantageCSP framework. It extends the functionality provided by System.Web.UI.Page to enhance interaction with AdvantageCSP components.

Interactions with AdvantageCSP Framework

  • SiteSettings: Provides access to the site settings module defined for the domain.
  • ConfigurationEngine: Reference to the AdvantageConfigurationEngine.
  • ModuleEngine: Reference to the AdvantageModuleEngine.
  • NavigationEngine: Reference to the AdvantageModuleEngine.
  • PageEngine: Reference to the AdvantageModuleEngine.
  • GetNavigations: Provides access to the navigations from the PageManagement.
  • CurrentDomain: Reference to the current domain.
  • CurrentLanguage: Reference to the current language.
  • CurrentSitePage: Reference to the SitePage (page content) that is being rendered.
  • CurrentNavigationPage: Reference to the Navigation that is being rendered.
  • CurrentSql: Reference to the current Advantage SQL connection context.

 

Methods

Name Description
CheckSSL Checks if the current page is being served over SSL (Secure Sockets Layer).
Dispose Releases all resources used by this instance.
GetNavigations Retrieves navigation links or paths based on specified criteria, aiding in the dynamic generation of site menus or navigation structures.
GetParameter Extracts and returns a parameter value from the query string of the current request.
LanguagePages Handles the language-specific rendering or organization of pages, potentially adjusting content based on the current language setting.
Modules Processes or manages modules related to a specified domain identifier, likely involving loading or rendering module content dynamically.
RegisterBottomScript (overloaded) Adds JavaScript or CSS content to the bottom of the page, useful for ensuring that scripts run after the page has loaded or for late-loading styles.
registerKeepAlive Possibly maintains or extends a session or connection alive, useful for web applications requiring long-lived connections.
RegisterTopScript (overloaded) Inserts JavaScript or CSS content at the top of the page, which is useful for defining styles or scripts that need to be loaded early in the page rendering process.
RenderControlContent Renders the content of a specific web control, possibly involving processing or manipulating the control's output before it is sent to the client.
SearchIndexUsingBrowserInstance Instructs the search indexing process to use a browser instance for rendering pages, allowing JavaScript and events to be processed. This approach may introduce overhead but is necessary for pages reliant on client-side scripting for content generation.
SetOpenGraph Configures Open Graph tags for the page, enhancing social media sharing capabilities by specifying how titles, descriptions, images, and more appear in shares.
SiteSettings() Retrieves custom site settings specific to the domain, allowing for domain-specific configurations to be applied dynamically.

 

Properties

Name Description
AdvantagePageDescription Gets or sets a descriptive text for the advantage page, which might be used for SEO or as a summary for the page.
AdvantagePageName Gets or sets the name of the advantage page, likely used for identifying pages within the site or for navigation.
AnalyticsCode Gets or sets the analytics tracking code, enabling site usage tracking and analytics capabilities.
ConfigurationEngine Provides access to the configuration engine, centralizing site configuration and settings management.
ContainerControl References the container control, possibly a parent control that holds other nested web controls.
CSPNonce Provides a nonce for the Content-Security-Policy header, enhancing security against certain attacks.
CurrentDomain Retrieves the domain currently being accessed, useful for multi-domain setups or domain-specific logic.
CurrentLanguage Indicates the language setting for the current session or page, facilitating multilingual content management.
CurrentNavigationPage Provides information about the currently rendered navigation page, aiding in dynamic navigation updates.
CurrentSitePage Accesses the current site page's content or settings, essential for rendering and customizing page content.
CurrentSql Grants access to the current SQL connection context, enabling database interactions specific to the current request.
DatabaseCacheManager Accesses the database cache manager, optimizing data retrieval and storage by caching domain/language-specific items.
Domain Retrieves the domain information, critical for applications that operate across multiple domains.

Advantage Layout Control

AdvantageLayoutControl Documentation

Members & Properties

The AdvantageLayoutControl is an ASP.NET control designed to manage layout within Advantage CSP pages. It provides functionalities for organizing and structuring content within a page layout.

An alternative method for creating layouts is to use the Dynamic Layout Manager in the CSP admin. (citation needed)

Overview

The AdvantageLayoutControl offers a flexible approach to designing page layouts within the Advantage CSP framework. It allows developers to define and manage various sections of a page, such as headers, footers, sidebars, and content areas.

Key Features

  • Organized Layout: Allows for easy structuring of page layout with different sections.
  • Customizable: Provides options for customization, allowing developers to define layout according to specific requirements.
  • Responsive Design: Supports responsive design principles, ensuring layouts adapt to different screen sizes and devices.
  • Integration: Seamlessly integrates with other Advantage CSP components and modules.

Usage

To use the AdvantageLayoutControl, simply include it within your ASP.NET page markup. You can then define the layout structure by adding child controls and setting properties as needed  for each section of the page (e.g., header, footer, sidebar) and configuring their properties to meet the design criteria.


Developers can define the layout statically in the ASPX page or dynamically through code-behind, offering further flexibility in how layouts are constructed and manipulated. The control's properties and child controls dictate the final appearance and structure of the page, allowing for detailed control over the layout.

Example

<%@ Control Language="C#" AutoEventWireup="true"  Inherits="AdvantageCMS.Core.Common.BaseClasses.AdvantageLayoutControl"  %>

<script runat="server">
    public override string AdvantageLayoutName{get { return "Full Width"; }}
    public override string AdvantageLayoutDescription { get { return ""; } }                 
</script>

<asp:Panel ID="pnlTopArea" ZoneName="Top Area" runat="server"></asp:Panel>

<asp:Panel ID="pnlMainArea" ZoneName="Main Area" runat="server"></asp:Panel>

Conclusion


The AdvantageLayoutControl is a powerful tool within the Advantage CSP framework, designed to ease the complexities of layout management in web development. Its emphasis on organization, customization, responsiveness, and seamless integration makes it a valuable asset for developers aiming to create sophisticated, user-friendly, and responsive websites.

 

Properties

The AdvantageLayoutControl provides the following properties:

Name Description
AdvantageLayoutDescription Gets the advantage layout description.
AdvantageLayoutName Gets the name of the advantage layout.
AdvantagePage Gets the advantage page.
Includes Gets or sets the includes.
Zones Gets the zones.

Data Components

Data Components

The "Data Components"  focuses on the elements within the Advantage CSP framework designed to facilitate data entry and management from the admin interface for display on the website's front end. This part of the framework ensures that content managers or administrators can efficiently input and update content that visitors will see on the live site. Let's delve into the specifics of these components, particularly focusing on Modules & Dialogs.

Overview

AdvantageModule: This is a front-end component used to display unstructured content on the website. "Unstructured" here implies that the content does not follow a rigid database schema or format, allowing for more flexible and varied content types such as text, images, videos, or custom HTML blocks. The AdvantageModule serves as a container for this content on the website, enabling it to be placed and styled according to the site's design requirements.

AdvantageAttributeControl: Accompanying the AdvantageModule is the AdvantageAttributeControl, a dialog-based control within the admin interface. This control is specifically designed for content managers to input or update the data that the AdvantageModule will display. It provides a user-friendly interface for managing the content of modules, ensuring that administrators can easily modify the website's content without needing to directly interact with the site's underlying code or databases.Modules & Dialogs

For unstructured page content the front end module (AdvantageModule) displays on the front end.  An associated dialog control (AdvavantageAttributeControl) is used to enter the data in the page manager.

Modules & Dialogs are registered in the System Administrator -> Module section.

   

 

Integration and Registration

System Administrator -> Module Section: To make these components available for use, they must be registered within the System Administrator area, under the Module section. This registration process involves specifying which modules and dialog controls are available for use, configuring settings related to their operation, and defining how they interact with the rest of the system.

Modules & Dialogs Registration: This registration is a crucial step as it ensures that the modules and dialogs are recognized by the Advantage CSP framework and can be properly utilized within the admin interface and reflected on the front end. It also allows for the setting of permissions, ensuring that only authorized users can edit or manage the content within these modules.

Benefits

Flexibility and Ease of Use: By separating the content management (via AdvantageAttributeControl) from the content display (via AdvantageModule), the framework allows for a flexible and intuitive approach to website content management. Administrators can easily update content without needing technical knowledge of web development, while developers can focus on the design and functionality of the website without being bogged down by content changes.

Customization and Scalability: The system allows for the customization of modules and dialogs, meaning that as the needs of the application grow or change, new types of content can be easily incorporated. This scalability is key to maintaining a dynamic and engaging website over time.

Conclusion

In summary, the Data Components of the Advantage CSP framework, particularly the Modules & Dialogs, offer a streamlined and efficient way for administrators to manage website content. By providing tools that are both powerful and user-friendly, the framework supports the ongoing need for websites to adapt and evolve their content to meet user needs and expectations.

AdvantageAttributeControl (Dialogs, Custom Properties)

 AdvantageAttributeControl: System.Web.UI.UserControl

Members & Properties

AdvantageAttributeControl is an ASP.NET control that extends System.Web.UI.UserControl. It serves multiple purposes within the AdvantageCSP framework, including acting as a dialog for customizing module content and as a "Custom Properties" control for enabling domain-specific custom logic during the rendering of an Advantage page.

Interactions with AdvantageCSP Framework

  • SiteSettings: Provides access to the site settings module defined for the domain.
  • ConfigurationEngine: A reference to the CMSConfigurationEngine.
  • ModuleEngine: A reference to the AdvantageModuleEngine.
  • AdminDomain: A reference to the current domain.
  • AdminLanguage: A reference to the current language.
  • CurrentSitePage: A reference to the SitePage (page content) being rendered.
  • CurrentNavigationPage: A reference to the Navigation being rendered.
  • CurrentSql: A reference to the current Advantage SQL connection context.
  • CurrentUser: A reference to the current logged-in user.
  • Attributes: Access to methods to set data.
  • ShowStatus: Renders a message to the user.

Primary Usage

To use AdvantageAttributeControl


Example

Html

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ContentAreaDialog.ascx.cs" Inherits="AdvantageClient.Modules_ContentAreaDialog" %>

<fieldset>
    <legend>
        Content Area
    </legend>

    <Advantage:AdvantageEditor id="edtContent" runat="server" ></Advantage:AdvantageEditor>        
</fieldset>

 

Code Behind

using AdvantageCMS.Core.Common.BaseClasses;

namespace AdvantageClient
{
    public partial class Modules_ContentAreaDialog : AdvantageAttributeControl
    {
        protected override void SaveDataToObject()
        {
            Attributes.Add("Content", edtContent.Content);
        }

        protected override void LoadDataFromObject(AdvantageAttributeArgs e)
        {
            edtContent.Content = SafeString(Attributes.GetString("Content"));
        }

        public override bool ValidateSave(out string message)
        {
            message = string.Empty;
            bool retval = true;

            if (string.IsNullOrEmpty(edtContent.Content))
            {
                message = "Please enter Content.<br/>";
                retval = false;
            }

            return retval;
        }
    }
}

Retrieving/Saving Data

 

SaveDataToObject()

This method is responsible for saving data from the control to an object.

  • In this specific implementation, it adds the content of the edtContent control to the Attributes collection (AdvantageAttributeArgs) under the key "Content".
  • This is typically called during the save process to persist user input or control states.
LoadDataFromObject(AdvantageAttributeArgs e):

This method loads data from an object into the control.

  • It takes an AdvantageAttributeArgs object as a parameter, which likely contains the data to be loaded.
  • In this implementation, it retrieves the content stored in the "Content" attribute of the Attributes collection and sets it to the edtContent control.
  • This method is typically called during the load process to restore previously saved data.

ValidateSave(out string message):

This method validates data before saving it.

  • It checks if the content of the edtContent control is empty or null.
  • If the content is missing, it sets an error message indicating that the user should enter the content.
  • This method returns a boolean value indicating whether the data is valid or not. If valid, it returns true; otherwise, it returns false, along with an error message.
  • This is often used to ensure data integrity and to prompt users to fill in required fields before proceeding with the save operation.

 

Conclusion

AdvantageAttributeControl provides a versatile tool for integrating custom logic and content customization within the AdvantageCSP framework. By leveraging its interactions with various framework components, developers can create dynamic and tailored user experiences for their web applications.

AdvantageModule

AdvantageModule: System.Web.UserControl

The Advantage module is the main front-end component responsible for rendering content to the user. It plays a crucial role in presenting information and functionality within the Advantage CSP system.

Methods & Properties

Registration

Once created, the module must be registered in the Advantage CSP admin under System Administrator -> Modules.

Data Retrieval

The module retrieves data primarily through the following sources:

  • Attributes Property: Provides data entered via the admin through the associated Dialog (AdvantageAttributeControl).
  • ModuleEngine: This object facilitates retrieval from the database of all "Structured Content".
  • SiteSettings: Custom control developed for your specific project and registered in the Domain Manager.

Caching

Because Advantage CSP is multi-site, multi-lingual,  The WebCacheManager is available to ensure that no cache is overwritten with the same name.

Example

ContentArea.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ContentArea.ascx.cs" Inherits="AdvantageClient.Modules_ContentArea" %>


    <asp:Literal ID="litContent" runat="server"></asp:Literal>

ContentArea.ascx.cs

using System;
using AdvantageCMS.Core.Common.BaseClasses;


namespace AdvantageClient
{
    public partial class Modules_ContentArea : AdvantageModule
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            litContent.Text = Attributes.GetString("Content");
        }
    }
}

 

AdvantageModuleRewrite

AdvantageModuleRewrite :AdvantageModule

Methods & Properties

AdvantageModuleRewrite is a front-end component that inherits from AdvantageModule. It provides additional functionality for URL rewriting and object handling.

Primary Properties

  • IsRewrite: boolean - True if this module is rewritten.
  • MyObject: <T> - Object type loaded with the specific record.

Usage

When on a page, if the URL ends with the SEO name of the specified object, the module will have the following properties set.

Implementation of the control requires <T> to be defined as the proper BusinessObject class.

Example

This example uses an Event Business Object.  The front-end module is able to determine if the page has been rewritten to a specified object.  If so, it will show the detail view.  If it is not rewritten, it will display a list of events.

Events.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Events.ascx.cs" Inherits="AdvantageClient.Modules_Events" %>

<!--Helper controls -->
<%@ Register Src="../../Controls/Navigation/Pagination.ascx" TagPrefix="uc1" TagName="Pagination" %>
<%@ Register Src="../../Controls/Helpers/DropdownCheckbox.ascx" TagPrefix="uc1" TagName="DropdownCheckbox" %>


<!--domain based style sheet-->
<asp:PlaceHolder runat="server" ID="phTop">

    <link href="/<%=CurrentDomain.FolderName %>/css/popper.css" rel="stylesheet">
</asp:PlaceHolder>


<asp:UpdatePanel runat="server" ID="upEvents">
    <ContentTemplate>
        <!-- List view (not rewritten) -->
        <asp:Panel runat="server" ID="pnlListView">
            <div class=" row col-sm-12">

                <asp:Panel runat="server" ID="pnlPosts" CssClass="col-lg-9 fade eventContent">
                    <asp:Repeater runat="server" ID="rptEventsList">
                        <ItemTemplate>
                            <asp:Panel CssClass="card mb-5 " runat="server" ID="pnlItem">
                                <div class="cardWrapper row ">
                                    <div class="col-sm-3 p-0">
                                        <advantage:AdvantageDisplayImage runat="server" ImageCssClass="img-fluid blogListImage" ID="aiImage" />
                                    </div>
                                    <div class="col col-sm-9 colContent">
                                        <h2 class="card-title h4">
                                            <asp:Literal runat="server" ID="litTitle" />
                                        </h2>
                                        <div class="meta mb-1">
                                            <span class="date">Published
                                                <asp:Literal runat="server" ID="litDate" /></span>
                                        </div>
                                        <div class="intro mb-2">
                                            <asp:Literal runat="server" ID="litSummary" />
                                        </div>
                                        <div class="intro mb-2">
                                            <asp:HyperLink class="btn btn-primary" runat="server" ID="hypButton"></asp:HyperLink>
                                        </div>
                                    </div>
                                </div>
                            </asp:Panel>
                        </ItemTemplate>
                    </asp:Repeater>
                    <asp:Repeater runat="server" ID="rptEventsCard">
                        <ItemTemplate>
                            <asp:Panel CssClass="card mb-5 " runat="server" ID="pnlItem">
                                <div class="cardWrapper">
                                    <asp:HyperLink class="img-circle link" runat="server" ID="hypImage">
                                        <advantage:AdvantageDisplayImage runat="server" ImageCssClass="img-fluid blogCardListImage" ID="aiImage" />
                                    </asp:HyperLink>
                                    <div class="card-body">
                                        <div class="small text-muted">
                                            <asp:Literal runat="server" ID="litDate" />
                                        </div>
                                        <h2 class="card-title h4">
                                            <asp:Literal runat="server" ID="litTitle" />
                                        </h2>
                                        <p class="card-text">
                                            <asp:Literal runat="server" ID="litSummary" />
                                        </p>
                                        <asp:HyperLink class="btn btn-primary" runat="server" ID="hypButton"></asp:HyperLink>
                                    </div>
                                </div>
                            </asp:Panel>
                        </ItemTemplate>
                    </asp:Repeater>
                </asp:Panel>

                <div class="col-lg-3">
                    <div class="col-sm-12">
                        <uc1:DropdownCheckbox runat="server" ID="DropdownCheckbox1" />
                    </div>
                    <div class="col-sm-12">
                        <div id="calendar"></div>
                    </div>
                </div>
            </div>

            <div class="blog container px-4">
                <uc1:Pagination runat="server" ID="pager1" />
            </div>
        </asp:Panel>
        
        <!-- Detail view (rewritten) -->
        <asp:Panel runat="server" ID="pnlDetailView">
            <div class="blogContainer">
                <asp:HyperLink runat="server" ID="hlURL" CssClass="btn btn-lg btn-primary">Return</asp:HyperLink>
                <br />
                <br />
                <article class="detail row">
                    <section class="sidebar col-md-4">
                        <advantage:AdvantageDisplayImage runat="server" ID="picDetail" DefaultImage="Mobile" />
                    </section>
                    <section class="main col-md-8">
                        <h2><%= MyObject.Title %></h2>

                        <time><%= MyObject.StartDate  %></time>

                        <div class="category">
                            <asp:HyperLink runat="server" ID="hlCategory"></asp:HyperLink>
                        </div>

                        <asp:PlaceHolder ID="phSummary" runat="server">
                            <p><%= MyObject.Summary %></p>
                        </asp:PlaceHolder>

                        <asp:PlaceHolder ID="phContent" runat="server">
                            <%= MyObject.Content %>
                        </asp:PlaceHolder>
                    </section>
                    
                    <!-- Tags -->
                    <asp:Repeater runat="server" ID="rptTags">
                        <HeaderTemplate>
                            <section class="tags">
                                <ul>
                        </HeaderTemplate>

                        <ItemTemplate>
                            <a href='<%# CurrentNavigationPage.FullUrl + "?tag=" + System.Net.WebUtility.UrlEncode(Container.DataItem.ToString()) %>'>#<%# Container.DataItem %></a>
                        </ItemTemplate>

                        <FooterTemplate>
                            </ul>
                        </section>
                       
                        </FooterTemplate>
                    </asp:Repeater>
                </article>
            </div>
        </asp:Panel>

        <!-- Call to trigger postback -->
        <asp:Button runat="server" ID="btnPostback" Style="display: none;" />

    </ContentTemplate>

</asp:UpdatePanel>


<%-- documentation https://fullcalendar.io/docs --%>

<asp:PlaceHolder runat="server" ID="phBottom">
    <!-- for Bootstrap 5 domain specific css/js-->
    <link href="/<%= CurrentDomain.FolderName %>/css/Calendar/bootstrap-icons.css" rel="stylesheet">

    <link href="/<%= CurrentDomain.FolderName %>/css/Calendar/calendar.css" rel="stylesheet" />
    <script src="/<%= CurrentDomain.FolderName %>/js/Calendar/calendar.js"></script>
    <script src="/Scripts/umd/popper.min.js"></script>
    <script src="/<%= CurrentDomain.FolderName %>/js/tooltip.min.js"></script>
    <script>

        function setCalendar(events, intialDate, startRange, endRange, listPath) {


            const calendarEl = document.getElementById('calendar');

            const calendar = new FullCalendar.Calendar(calendarEl,
                {
                    eventDidMount: function (info) {
                        var tooltip = new Tooltip(info.el, {
                            title: '<table><tr><td style="font-weight:bold;">' + info.event.title + '</td></tr><tr><td>' + info.event.extendedProps.summary + '</td></tr><tr><td>' + info.event.start.toLocaleDateString('en-us', { weekday: "long", year: "numeric", month: "short", day: "numeric" }) + '</td></tr></table>',
                            placement: 'top',
                            trigger: 'hover',
                            container: 'body',
                            html: true
                        });
                    },
                    eventClick: function (info) {
                        document.location.href = listPath + info.event.extendedProps.seoName;
                        info.jsEvent.preventDefault(); // prevents browser from following link in current tab.
                    },
                    handleWindowResize: true,
                    themeSystem: 'bootstrap5',
                    height: 'auto',
                    contentHeight: 400,
                    expandRows: true,
                    headerToolbar: {
                        left: 'title',
                        right: 'prev,next'
                    },
                    initialView: 'dayGridMonth',
                    initialDate: intialDate,
                    navLinks: true, // can click day/week names to navigate views
                    editable: true,
                    selectable: true,
                    nowIndicator: true,
                    dayMaxEvents: true, // allow "more" link when too many events
                    events: events,
                    validRange: {
                        start: startRange,
                        end: endRange
                    }
                });

            calendar.render();
            document.getElementById("<%= pnlPosts.ClientID %>").classList.add("show");
        }


        //Dropdown list will call this function to process changes.
        function AdvSetCategory_ClientScriptId(sender, items) {
            var url = AdvUpdateQueryString_ClientScriptId("tag", "");
            const values = items.map(item => item.value);
            const valueList = values.join('.');
            url = AdvUpdateQueryString_ClientScriptId("category", valueList, url);
            AdvResetPagination_ClientScriptId(url);
        }


        function AdvUpdateQueryString_ClientScriptId(key, value, url) {
            if (!url) url = window.location.href;
            const theUrl = new URL(url);
            const search_params = theUrl.searchParams;
            if (value === null || value === "")
                search_params.delete(key);
            else
                search_params.set(key, value);
            theUrl.search = search_params.toString();
            return theUrl;
        }

        function AdvResetPagination_ClientScriptId(url) {
            if (url.href !== window.location.href) {
                url.hash = '';
                refreshList(url.href);
            }
        }

        function refreshList(url) {

            var addPush = url !== null;

            if (url === null) url = window.location.pathname + window.location.search;
            if (addPush) window.history.pushState("", "", url);

            var el = document.getElementById('<%=this.Page.Form.ClientID%>');
            if (el == null)
                el = document.getElementsByTagName('body')[0].getElementsByTagName('form')[0];
            if (el != null)
                el.setAttribute('action', url);

            __doPostBack('<%= btnPostback.ClientID%>', '');

        }

        window.addEventListener('popstate', function (event) { refreshList(null); });
    </script>
</asp:PlaceHolder>

Events.ascx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mime;
using System.Web;
using System.Web.UI.WebControls;
using AdvantageCMS.Core.Common;
using AdvantageCMS.Core.Common.BaseClasses;

using AdvantageCMS.Core.Common.Enums;
using AdvantageCMS.Core.Utils;
using AdvantageCMS.Web.UI;
using Newtonsoft.Json;


namespace AdvantageClient

{

    public partial class Modules_Events : AdvantageModuleRewrite<Event>
    {
        private void SetDialogValues()
        {
            _detailPath = Attributes.GetString("DetailPath");
            _listPath = Attributes.GetString("ListPath");
            ItemsPerRow = Attributes.GetString("ItemsPerRow").ToInteger(1);
            ItemsPerPage = Attributes.GetInt("ItemsPerPage").ToInteger(0);
            ButtonText = Attributes.GetString("ButtonText");
            pager1.PageIndexChanged += Pager1_OnPageIndexChanged;
            _pageId = (HttpContext.Current?.Request["page"] ?? "1").ToInteger(1);
        }


        #region Page Events

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            rptEventsCard.ItemDataBound += rptEvent_ItemDataBound;
            rptEventsList.ItemDataBound += rptEvent_ItemDataBound;

            SetDialogValues();
        }


        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            //Show Panel and initialize on a detail record or a list view depending on if rewritten
            if (IsReWrite)
            {
                pnlListView.Visible = false;
                pnlDetailView.Visible = true;
                hlURL.NavigateUrl = ListPath.Substring(0,ListPath.Length-1);
                setImage(picDetail, MyObject);
            }
            else
            {
                pnlListView.Visible = true;
                pnlDetailView.Visible = false;
         
                Page.ClientScript.GetPostBackEventReference(this, "");
                Categories = Server.UrlDecode(UrlUtil.GetParameter(Request.RawUrl, "Category"));
                if (ItemsPerPage > 0)
                    pager1.SetPagination(SelectedEvents.Count, ItemsPerPage);
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            if (!IsReWrite)
            {
                LoadDropDown();
                RegisterTopScript(phTop);
                var script = this.RenderControlContent(phBottom).Replace("_ClientScriptId", "_" + this.ClientID);
                phBottom.Visible = false;
                RegisterBottomScript(phBottom.ClientID, script);

                Helper.Registerpostbackscript($"setCalendar({EventArray},'{InitialDate}','{StartRange}','{EndRange}', '{ListPath}');");

                BindList(PageId);
            }

            base.OnPreRender(e);

        }
        #endregion Page Events


        #region List Events and Methods

        private void Pager1_OnPageIndexChanged(object sender, int page)
        {
            _pageId = page;
        }
        private void BindList(int pageNum)
        {
            var ds = SelectedEvents;

            if (ItemsPerPage > 0)
            {
                ;
                ds = ds.Skip((pageNum - 1) * ItemsPerPage).ToList();
                ds = ds.Take(ItemsPerPage).ToList();
            }

            if (ItemsPerRow == 1)
            {
                rptEventsList.DataSource = ds;
                rptEventsList.DataBind();
                rptEventsList.Visible = false;
                rptEventsList.Visible = true;
            }
            else
            {
                rptEventsCard.DataSource = ds;
                rptEventsCard.DataBind();
                rptEventsList.Visible = false;
                rptEventsCard.Visible = true;
            }
        }
        private void rptEvent_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            Event itm = ((Event)e.Item.DataItem);
            Panel pnlItem = e.Item.FindControl("pnlItem") as Panel;
            AdvantageDisplayImage aiImage = e.Item.FindControl("aiImage") as AdvantageDisplayImage;
            HyperLink hypButton = e.Item.FindControl("hypButton") as HyperLink;
            HyperLink hypImage = e.Item.FindControl("hypImage") as HyperLink;
            Literal litTitle = e.Item.FindControl("litTitle") as Literal;
            Literal litSummary = e.Item.FindControl("litSummary") as Literal;
            Literal litDate = e.Item.FindControl("litDate") as Literal;

            if (pnlItem != null) pnlItem.CssClass += $" {ItemsPerRowCss}";
            setImage(aiImage, itm);
            if (hypButton != null)
            {
                hypButton.NavigateUrl = DetailPath + itm.SEOName;
                hypButton.Text = ButtonText;
            }

            if (litTitle != null) litTitle.Text = itm.Title;
            if (litSummary != null) litSummary.Text = itm.Summary;

            if (hypImage != null)
                hypImage.NavigateUrl = DetailPath + itm.SEOName;

            if (litDate != null) litDate.Text = itm.StartDate.ToShortDateString();
        }

        private void setImage(AdvantageDisplayImage aiImage, Event itm)
        {
            //if we have a custom image in the event, use it.  If not, use the image from the eventtype.
            if (aiImage != null)
            {
                if ((itm.Image?.ActiveImageElements?.Count ?? 0) > 0 &&
                    itm.Image.ActiveImageElements.Any(ee => (ee.ImageUrl ?? "") != ""))
                    aiImage.AdvantageImage = itm.Image;
                else
                {
                    EventType et = EventTypes.FirstOrDefault(ee => ee.MasterID.Equals(itm.EventType));
                    if ((et?.Image?.ActiveImageElements?.Count ?? 0) > 0 &&
                        et.Image.ActiveImageElements.Any(ee => (ee.ImageUrl ?? "") != ""))
                        aiImage.AdvantageImage = et.Image;
                }
            }
        }

        private void LoadDropDown()
        {
            bool openDdl = (IsPostBack && LastCategories != Categories);
            LastCategories = Categories;
            DropdownCheckbox1.OnChange = "AdvSetCategory_" + this.ClientID;
            DropdownCheckbox1.OpenDropDown = openDdl;
            if (DropdownCheckbox1.Control.Items.Count == 0)
            {
                var x = Events.Select(ee => ee.EventType).Distinct().ToList();
                ModuleEngine.GetPublishedObjectByMasterIds<EventType>(x);
                DropdownCheckbox1.Control.DataValueField = "SEOName";
                DropdownCheckbox1.Control.DataTextField = "Name";
                DropdownCheckbox1.Control.DataSource = ModuleEngine.GetPublishedObjectByMasterIds<EventType>(x);
                DropdownCheckbox1.Control.DataBind();
            }

            foreach (ListItem item in DropdownCheckbox1.Control.Items)
                item.Selected = SelectedEventTypes.Count == 0 || SelectedEventTypes.Any(ee => ee.SEOName.ToString().Equals(item.Value));



        }

        #endregion List Events and Methods

        #region  Properties

        private int _pageId = 1;
        private int PageId
        { get { return _pageId; } }


        private string _detailPath;
        protected string DetailPath
        {
            get
            {

                if (string.IsNullOrEmpty(_detailPath))
                    _detailPath = ClientHelper.GetItemPath(this.Page, true, IsReWrite);
                return _detailPath;
            }
        }
        private string _listPath;

        protected string ListPath
        {
            get
            {
                if (string.IsNullOrEmpty(_listPath))
                    _listPath = ClientHelper.GetItemPath(this.Page, false, IsReWrite);
                return _listPath;
            }
        }


        private string _buttonText = "Event Details";
        protected string ButtonText
        {
            get { return _buttonText; }
            set
            {
                if (!string.IsNullOrEmpty(value)) _buttonText = value;
            }
        }
        protected int ItemsPerPage { get; set; } = 9;
        protected int ItemsPerRow { get; set; } = 1;
        protected string ItemsPerRowCss
        {
            get
            {

                if (ItemsPerRow == 1)
                    return " col-lg-12 ";
                else if (ItemsPerRow == 2)
                    return " col-lg-6 ";
                else
                    return " col-lg-12 ";
            }
        }
        protected string LastCategories
        {
            get { return ViewState["LastCategories"].ToString(); }
            set { ViewState["LastCategories"] = value; }
        }
        protected string Categories { get; set; }

        protected List<string> CategoryList { get { return Categories.Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries).ToList(); } }

        
        private List<EventType> _eventsTypes = null;
        public List<EventType> EventTypes
        {
            get
            {
                if (_eventsTypes == null)
                    _eventsTypes = ModuleEngine.GetAllPublishedObjects<EventType>().Where(ee=>Events.Any(y=>y.EventType.Equals(ee.MasterID))).ToList();
 
                return _eventsTypes;
            }
        }

        private List<EventType> _selectedEventTypes = null;
        public List<EventType> SelectedEventTypes
        {
            get
            {
              
                if (_selectedEventTypes == null)
                    _selectedEventTypes = EventTypes.Where(ee => CategoryList.Any(y => ee.SEOName.Equals(y))).ToList();
               

                return _selectedEventTypes;
            }
        }
     
     
        private List<Event> _events = null;
        public List<Event> Events
        {
            get
            {
                if (_events == null)
                    _events = ModuleEngine.GetPublishedObjectsBykey<Event>("StartDate", eComparison.GreaterOrEquals,
                        DateTime.Now.AddDays(-30)).OrderBy(ee=>ee.StartDate).ToList();
              

                return _events;
            }
        }

        private List<Event> _selectedEvents = null;
        public List<Event> SelectedEvents
        {
            get
            {
                if (_selectedEvents == null)
                {
                    _selectedEvents = Events;
                    if (SelectedEventTypes!=null && SelectedEventTypes.Count>0)
                        _selectedEvents = _selectedEvents.Where(ee => SelectedEventTypes.Any(y => ee.EventType.Equals(y.MasterID))).OrderBy(ee => ee.StartDate).ToList();


                }

                return _selectedEvents;
            }
        }

        public string EventArray
        {
            get
            {
                if (SelectedEvents == null) return null;
                return  JsonConvert.SerializeObject(SelectedEvents.Select(ee => ee.CalendarItem).ToList());
            }
        }

        public string InitialDate
        {
            get { return DateTime.Now.ToString("yyy-MM-dd"); }
        }

        public string StartRange
        {
            get
            {
                var min = Events.Min(ee => ee.StartDate);
                min = new DateTime(min.Year, min.Month, 1);
                return min.ToString("yyy-MM-dd");
            }
        }

        public string EndRange
        {
            get
            {
                var max = Events.Max(ee => ee.EndDate);
                max = new DateTime(max.Year, max.Month + 1, 1).AddDays(-1);
                return max.ToString("yyy-MM-dd");
            }
        }

        public string Styles
        {
            get
            {
                string s = string.Empty;
              var x=  ModuleEngine.GetAllPublishedObjects<EventType>();
              foreach (EventType type in x)
                s += type.CssClasses + Environment.NewLine;
              return s;
            }
        }

        #endregion  Properties




    }
}

 

SiteSettings

TODO
Back to Top Button