SplendidCRM Module Development Guide

Introduction

SplendidCRM is both database driven and data driven.  SplendidCRM uses database schema information during the design phase and in the reporting module.  SplendidCRM uses layout data to determine the fields to display in edit, detail or list views.  Creating a new module requires that you create the underlying tables, the views, the procedures and the layout data.

The following is the sequence of operations when you create a new module:

1.      Create the table scripts.

2.      Create the view scripts.

3.      Create the procedure scripts.

4.      Create the data scripts.

a.       Create the data scripts for the MODULES table.

b.      Create the data scripts for the SHORTCUTS table.

c.       Create the data scripts for the TERMINOLOGY table.

d.      Create the data scripts for the GRIDVIEWS_COLUMNS tables.

e.       Create the data scripts for the EDITVIEWS_FIELDS tables.

f.       Create the data scripts for the DETAILVIEWS_FIELDS tables.

g.      Create the data scripts for the DYNAMIC_BUTTONS table.

h.      Create the data scripts for the DETAILVIEW_RELATIONSHIPS table.

5.      Create the ASP.NET code.

a.       Create the ListView code.

b.      Create the EditView code.

c.       Create the DetailView code.

d.      Create the PopupView code.

e.       Create the relationship controls.

 


Create the Database Schema Scripts

SplendidCRM is a database application, so the creation of a new module will require that you create a database table to store the module information.  The quickest way to create a new module is to start with an existing module and perform search-and-replace operations.  The source code included in this document is intended to be complete, so that you can treat this code as a template.

This document will use the SplendidCRM Teams module as a real-world example of how a module is created.

Create the Table Scripts

A SplendidCRM table will always start with the following six fields:

ID

Primary Key

DELETED

Flag used to mark the record as deleted.

CREATED_BY

User ID who created the record.

DATE_ENTERED

Date the record was created.

MODIFIED_USER_ID

User ID who last modified the record.

DATE_MODIFIED

Date the record was last modified.

 

All tables will have an ID field to serve as its primary key.  We always provide a default value for the primary key so that records can be inserted without having to first define a unique value for the ID field.  We also provide default values for the deleted field and the date-related auditing fields.  We refer to the date and user tracking fields as auditing fields because they are used to track changes to the record.


In our Teams module, the only other fields in the table are NAME, DESCRIPTION and PRIVATE.  Observe that we use nvarchar instead of varchar and ntext instead of text.  The letter “n” is used because SplendidCRM uses Unicode UTF-8 to ensure full multi-lingual support.

TEAMS.1.sql

if not exists (select * from dbo.sysobjects where id = object_id(N'dbo.TEAMS') and OBJECTPROPERTY(id, N'IsUserTable') = 1)

  begin

          print 'Create Table dbo.TEAMS';

          Create Table dbo.TEAMS

                   ( ID               uniqueidentifier not null default(newid()) constraint PK_TEAMS primary key

                   , DELETED          bit not null default(0)

                   , CREATED_BY       uniqueidentifier null

                   , DATE_ENTERED     datetime not null default(getdate())

                   , MODIFIED_USER_ID uniqueidentifier null

                   , DATE_MODIFIED    datetime not null default(getdate())

 

                   , NAME             nvarchar(128) not null

                   , DESCRIPTION      ntext null

                   , PRIVATE          bit null

                   )

  end

GO

 

SplendidCRM allows the dynamic creation of fields in most modules.  When a field is created, we place that field in a table whose name matches the module name, but ends in _CSTM.  If the module allows custom fields, we must create this table.

The custom table has no auditing fields because we rely upon the base table for that information.  The custom table has an ID_C field instead of an ID field so that we can easily join the two tables and ensure that no fields would overlap.  You will see how we do this in the next section.

TEAMS_CSTM.2.sql

if not exists (select * from dbo.sysobjects where id = object_id(N'dbo.TEAMS_CSTM') and OBJECTPROPERTY(id, N'IsUserTable') = 1)

  begin

          print 'Create Table dbo.TEAMS_CSTM';

          Create Table dbo.TEAMS_CSTM

                   ( ID_C                               uniqueidentifier not null constraint PK_TEAMS_CSTM primary key

                   )

  end

GO

 


Create the View Scripts

Any time the SplendidCRM application retrieves data from the database, it does so using a view.  The primary reason why we use a view is to join the base table with the most-often used relationships.  We always join the base view to the users table so that we can include the user name of the creator of the record and the last user to modify the record.  If the module allows custom fields, then we also join to the custom table for that module.

The use of TEAMS_CSTM.* is our trick to allow the view to grow as fields are added to the custom table.

vwTEAMS.1.sql

if exists (select * from dbo.sysobjects where id = object_id(N'dbo.vwTEAMS') and OBJECTPROPERTY(id, N'IsView') = 1)

          Drop View dbo.vwTEAMS;

GO

 

 

Create View dbo.vwTEAMS

with encryption

as

select TEAMS.ID

     , TEAMS.NAME

     , TEAMS.DESCRIPTION

     , TEAMS.PRIVATE

     , TEAMS.DATE_ENTERED

     , TEAMS.DATE_MODIFIED

     , USERS_CREATED_BY.USER_NAME  as CREATED_BY

     , USERS_MODIFIED_BY.USER_NAME as MODIFIED_BY

     , TEAMS_CSTM.*

  from            TEAMS

  left outer join USERS USERS_CREATED_BY

               on USERS_CREATED_BY.ID  = TEAMS.CREATED_BY

  left outer join USERS USERS_MODIFIED_BY

               on USERS_MODIFIED_BY.ID = TEAMS.MODIFIED_USER_ID

  left outer join TEAMS_CSTM

               on TEAMS_CSTM.ID_C      = TEAMS.ID

 where TEAMS.DELETED = 0

 

GO

 

Grant Select on dbo.vwTEAMS to public;

GO

 


As a general rule, we always create three views for each module.  The first is the base view, the second is the view that is used in the ListView area and the third view is used in both the DetailView and EditView areas.  While creating three views is not absolutely necessary, it does provide the opportunity to provide additional joins or calculated fields in either the ListView or DetailView areas. 

In our example, we select all fields from the base view.

vwTEAMS_List.2.sql

if exists (select * from dbo.sysobjects where id = object_id(N'dbo.vwTEAMS_List') and OBJECTPROPERTY(id, N'IsView') = 1)

          Drop View dbo.vwTEAMS_List;

GO

 

 

Create View dbo.vwTEAMS_List

with encryption

as

select *

  from vwTEAMS

 

GO

 

Grant Select on dbo.vwTEAMS_List to public;

GO

 

vwTEAMS_Edit.2.sql

if exists (select * from dbo.sysobjects where id = object_id(N'dbo.vwTEAMS_Edit') and OBJECTPROPERTY(id, N'IsView') = 1)

          Drop View dbo.vwTEAMS_Edit;

GO

 

 

Create View dbo.vwTEAMS_Edit

with encryption

as

select *

  from vwTEAMS

 

GO

 

Grant Select on dbo.vwTEAMS_Edit to public;

GO

 


Create the Procedure Scripts

Anytime the SplendidCRM application inserts data into the database, it does so using a stored procedure.  Most of the stored procedures in the system are as simple as the one in our example.  Observe that we have combined the insert and update operations into a single stored procedure.  Also observe that the @ID field is an input/output parameter and that we assign it a new value if it is empty.   Finally, observe that we insert a record into the custom table if such a record does not already exist.

spTEAMS_Update.1.sql

if exists (select * from dbo.sysobjects where id = object_id(N'spTEAMS_Update') and OBJECTPROPERTY(id, N'IsProcedure') = 1)

          Drop Procedure dbo.spTEAMS_Update;

GO

 

Create Procedure dbo.spTEAMS_Update

@ID                uniqueidentifier output

@MODIFIED_USER_ID  uniqueidentifier

@NAME              nvarchar(128)

@DESCRIPTION       ntext

          )

with encryption

as

  begin

          set nocount on

         

          if not exists(select * from TEAMS where ID = @ID) begin -- then

                   if dbo.fnIsEmptyGuid(@ID) = 1 begin -- then

                             set @ID = newid();

                   end -- if;

                   insert into TEAMS

                             ( ID              

                             , CREATED_BY      

                             , DATE_ENTERED    

                             , MODIFIED_USER_ID

                             , DATE_MODIFIED   

                             , NAME            

                             , DESCRIPTION     

                             )

                   values @ID              

                   @MODIFIED_USER_ID

                             ,  getdate()       

                   @MODIFIED_USER_ID

                             ,  getdate()       

                   @NAME            

                   @DESCRIPTION     

                             );

          end else begin

                   update TEAMS

                      set MODIFIED_USER_ID  = @MODIFIED_USER_ID

                        , DATE_MODIFIED     =  getdate()       

                        , NAME              = @NAME            

                        , DESCRIPTION       = @DESCRIPTION     

                    where ID                = @ID               ;

          end -- if;

 

          if not exists(select * from TEAMS_CSTM where ID_C = @ID) begin -- then

                   insert into TEAMS_CSTM ( ID_C ) values ( @ID );

          end -- if;  end

GO

 

Grant Execute on dbo.spTEAMS_Update to public;

GO

 


Every module has a stored procedure to delete a record.  It most cases, we do not actually delete the record, we just set the DELETED flag to 1.  In the Teams example, observe how we do the additional work of cleaning up related tables.  This is an example of our use of the stored procedures to contain business logic.  As much as possible, we prefer to put the business logic in the database.

spTEAMS_Delete.1.sql

if exists (select * from dbo.sysobjects where id = object_id(N'spTEAMS_Delete') and OBJECTPROPERTY(id, N'IsProcedure') = 1)

          Drop Procedure dbo.spTEAMS_Delete;

GO

 

Create Procedure dbo.spTEAMS_Delete

@ID               uniqueidentifier

@MODIFIED_USER_ID uniqueidentifier

          )

with encryption

as

  begin

          set nocount on

         

          -- BEGIN Oracle Exception

                   update TEAMS

                      set DELETED          = 1

                        , DATE_MODIFIED    = getdate()

                        , MODIFIED_USER_ID = @MODIFIED_USER_ID

                    where ID = @ID;

          -- END Oracle Exception

 

          -- BEGIN Oracle Exception

                   update TEAM_NOTICES

                      set DELETED          = 1

                        , DATE_MODIFIED    = getdate()

                        , MODIFIED_USER_ID = @MODIFIED_USER_ID

                    where TEAM_ID = @ID;

          -- END Oracle Exception

 

          -- BEGIN Oracle Exception

                   update TEAM_MEMBERSHIPS

                      set DELETED          = 1

                        , DATE_MODIFIED    = getdate()

                        , MODIFIED_USER_ID = @MODIFIED_USER_ID

                    where TEAM_ID = @ID;

          -- END Oracle Exception

  end

GO

 

Grant Execute on dbo.spTEAMS_Delete to public;

GO

 


Create the Data Scripts

SplendidCRM is heavily data-driven, so in order to display or edit a module record, you must first define the data for the module.  The place to start is the MODULES table.  Any time we insert configuration data, we almost always do so using an Insert Only stored procedure.  The purpose of an Insert Only stored procedure is to ensure that the record is inserted only if it does not exist. 

Create the Data Scripts for the MODULES Table

The MODULES table stores critical information about the module, for example, if it is for administration purposes, or if it is customizable.

exec dbo.spMODULES_InsertOnly null, 'Teams', '.moduleList.Teams', '~/Administration/Teams/', 1, 0,  0, 0, 0, 0, 0, 1, 'TEAMS', 0;

exec dbo.spACL_ACTIONS_Initialize;

 

The following is the definition of each field in the spMODULES_InsertOnly stored procedure:

@MODIFIED_USER_ID

uniqueidentifier

This field is typically null.

@MODULE_NAME

nvarchar(25)

Name of the module.  It will be used in all the other data scripts.

@DISPLAY_NAME

nvarchar(50)

Typically a reference to a moduleList terminology entry.

@RELATIVE_PATH

nvarchar(50)

The relative path to the module in the web application.

@MODULE_ENABLED

bit

Enabled flag.  It is typically enabled.

@TAB_ENABLED

bit

Tab menu enabled flag.  Show or hide the module on the tab menu of the application.

@TAB_ORDER

int

Tab order for the menu of the application.

@PORTAL_ENABLED

bit

This flag is not used.

@CUSTOM_ENABLED

bit

Enable the custom field editor for this module.

@REPORT_ENABLED

bit

Enable reports on this module.

@IMPORT_ENABLED

bit

Enable importing data into this module.

@IS_ADMIN

bit

Mark the module as admin-only.

@TABLE_NAME

nvarchar(30)

Base table for the module.

@MOBILE_ENABLED

bit

Enable the module to be visible on the mobile tab menu.


Create the Data Scripts for the SHORTCUTS Table

The shortcuts typically appear on the left panel of the web application.  Most modules have two shortcuts, one to create a new module record and the other to list all records.

if not exists (select * from SHORTCUTS where MODULE_NAME = 'Teams' and DELETED = 0) begin -- then

          exec dbo.spSHORTCUTS_InsertOnly null, 'Teams', 'Teams.LNK_NEW_TEAM', '~/Administration/Teams/edit.aspx', 'CreateTeams.gif', 1,  1, 'Teams', 'edit';

          exec dbo.spSHORTCUTS_InsertOnly null, 'Teams', 'Teams.LNK_TEAM_LIST', '~/Administration/Teams/default.aspx', 'Teams.gif', 1,  2, 'Teams', 'list';

end -- if;

 

The following is the definition of each field in the spSHORTCUTS_InsertOnly stored procedure:

@MODIFIED_USER_ID

uniqueidentifier

This field is typically null.

@MODULE_NAME

nvarchar(25)

Name of the module that this shortcut belongs to.

@DISPLAY_NAME

nvarchar(150)

Typically a reference to a terminology entry.

@RELATIVE_PATH

nvarchar(255)

Relative path shortcut.

@IMAGE_NAME

nvarchar(50)

Image name for the shortcut.

@SHORTCUT_ENABLED

bit

Enable the shortcut.

@SHORTCUT_ORDER

int

Display order for the shortcuts.

@SHORTCUT_MODULE

nvarchar(25)

Target module.  It is typically the same module, but a shortcut list can have links to other modules.

@SHORTCUT_ACLTYPE

nvarchar(100)

Access right that will be required.

 


Create the Data Scripts for the TERMINOLOGY Table

All text strings come from the TERMINOLOGY table.  When the application starts, all terms are loaded into the application cache for all languages that are enabled. 

When referencing a term in the database, use the format MODULE_NAME + “.” + NAME.  As a general rule, the lists do not define a module name, so the format for a list entry is “.” + LIST_NAME + “.” + NAME.

exec dbo.spTERMINOLOGY_InsertOnly N'Teams'                 , N'en-US', null, N'moduleList', 44, N'Teams';

 

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_DESCRIPTION'       , N'en-US', N'Teams', null, null, N'Description:';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_LIST_DESCRIPTION'  , N'en-US', N'Teams', null, null, N'Description';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_LIST_FORM_TITLE'   , N'en-US', N'Teams', null, null, N'Team List';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_LIST_MEMBERSHIP'   , N'en-US', N'Teams', null, null, N'Membership';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_LIST_NAME'         , N'en-US', N'Teams', null, null, N'Team Name';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_LIST_PRIVATE'      , N'en-US', N'Teams', null, null, N'Private';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_LIST_TEAM'         , N'en-US', N'Teams', null, null, N'Team';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_NAME'              , N'en-US', N'Teams', null, null, N'Team Name:';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_PRIVATE'           , N'en-US', N'Teams', null, null, N'Private:';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_SEARCH_FORM_TITLE' , N'en-US', N'Teams', null, null, N'Team Search';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_TEAM'              , N'en-US', N'Teams', null, null, N'Team:';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_TEAMS'             , N'en-US', N'Teams', null, null, N'Teams';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_ENABLE'            , N'en-US', N'Teams', null, null, N'Enable';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_DISABLE'           , N'en-US', N'Teams', null, null, N'Disable';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_REQUIRE'           , N'en-US', N'Teams', null, null, N'Require';

exec dbo.spTERMINOLOGY_InsertOnly N'LBL_OPTIONAL'          , N'en-US', N'Teams', null, null, N'Optional';

exec dbo.spTERMINOLOGY_InsertOnly N'LNK_NEW_TEAM'          , N'en-US', N'Teams', null, null, N'Create Team';

exec dbo.spTERMINOLOGY_InsertOnly N'LNK_TEAM_LIST'         , N'en-US', N'Teams', null, null, N'Teams';

 

The following is the definition of each field in the spTERMINOLOGY_InsertOnly stored procedure:

@NAME

nvarchar(50)

Name for the term.

@LANG

nvarchar(10)

Language code.

@MODULE_NAME

nvarchar(25)

Module name.

@LIST_NAME

nvarchar(50)

List name.

@LIST_ORDER

int

List order.

@DISPLAY_NAME

nvarchar(2000)

Display name.

 


Create the Data Scripts for the GRIDVIEWS_COLUMNS Table

 

 

if not exists(select * from GRIDVIEWS_COLUMNS where GRID_NAME = 'Teams.ListView' and DELETED = 0) begin -- then

          print 'GRIDVIEWS_COLUMNS Teams.ListView';

          exec dbo.spGRIDVIEWS_InsertOnly           'Teams.ListView', 'Teams', 'vwTEAMS_List';

          exec dbo.spGRIDVIEWS_COLUMNS_InsHyperLink 'Teams.ListView', 1, 'Teams.LBL_LIST_NAME', 'NAME', 'NAME', '20%', 'listViewTdLinkS1', 'ID', '~/Administration/Teams/view.aspx?id={0}', null, 'Teams', null;

          exec dbo.spGRIDVIEWS_COLUMNS_InsBound     'Teams.ListView', 2, 'Teams.LBL_LIST_DESCRIPTION', 'DESCRIPTION', 'DESCRIPTION', '50%';

end -- if;

 

The following is the definition of each field in the spGRIDVIEWS_InsertOnly stored procedure:

@NAME

nvarchar(50)

Name for the grid view.

@MODULE_NAME

nvarchar(25)

Module that this view applies to.

@VIEW_NAME

nvarchar(50)

SQL view for the grid view.

 

The following is the definition of each field in the spGRIDVIEWS_COLUMNS_InsHyperLink stored procedure:

@GRID_NAME

nvarchar(50)

Name of the grid view.

@COLUMN_INDEX

int

Index of the field.

@HEADER_TEXT

nvarchar(150)

Terminology name used in the header.

@DATA_FIELD

nvarchar(50)

Field name.

@SORT_EXPRESSION

nvarchar(50)

Field that will be sorted.  Usually the same as the DATA_FIELD.

@ITEMSTYLE_WIDTH

nvarchar(10)

HTML table column width.

@ITEMSTYLE_CSSCLASS

nvarchar(50)

HTML style sheet class name.

@URL_FIELD

nvarchar(50)

Field used in the URL.

@URL_FORMAT

nvarchar(100)

Format for the URL with {0} style replacements.

@URL_TARGET

nvarchar(20)

HTML target for the URL.

@URL_MODULE

nvarchar(25)

Target module.  Used for access control.

@URL_ASSIGNED_FIELD

nvarchar(30)

Target module Assigned field.  Used for access control.

 

The following is the definition of each field in the spGRIDVIEWS_COLUMNS_InsBound stored procedure:

@GRID_NAME

nvarchar(50)

Name of the grid view.

@COLUMN_INDEX

int

Index of the field.

@HEADER_TEXT

nvarchar(150)

Terminology name used in the header.

@DATA_FIELD

nvarchar(50)

Field name.

@SORT_EXPRESSION

nvarchar(50)

Field that will be sorted.  Usually the same as the DATA_FIELD.

@ITEMSTYLE_WIDTH

nvarchar(10)

HTML table column width.

 


Create the Data Scripts for the EDITVIEWS_FIELDS Table

 

if not exists(select * from EDITVIEWS_FIELDS where EDIT_NAME = 'Teams.EditView' and DELETED = 0) begin -- then

          print 'EDITVIEWS_FIELDS Teams.EditView';

          exec dbo.spEDITVIEWS_InsertOnly          'Teams.EditView', 'Teams', 'vwTEAMS_Edit', '15%', '85%', null;

          exec dbo.spEDITVIEWS_FIELDS_InsBound     'Teams.EditView',  0, 'Teams.LBL_NAME', 'NAME', 1, 1, 128, 35, null;

          exec dbo.spEDITVIEWS_FIELDS_InsBlank     'Teams.EditView',  1, null;

          exec dbo.spEDITVIEWS_FIELDS_InsMultiLine 'Teams.EditView',  2, 'Teams.LBL_DESCRIPTION', 'DESCRIPTION', 0, 2,   4, 60, null;

end -- if;

 

The following is the definition of each field in the spEDITVIEWS_InsertOnly stored procedure:

@NAME

nvarchar(50)

Name for the edit view.

@MODULE_NAME

nvarchar(25)

Module that this view applies to.

@VIEW_NAME

nvarchar(50)

SQL view for the edit view.

@LABEL_WIDTH

nvarchar(10)

Width of the label.  Typically 15%.

@FIELD_WIDTH

nvarchar(10)

Width of the field.  Typically 35%.

@DATA_COLUMNS

int

Number of data columns.  Typically 2.

 

The following is the definition of each field in the spEDITVIEWS_FIELDS_InsBound stored procedure:

@EDIT_NAME

nvarchar(50)

Name of the edit view.

@FIELD_INDEX

Int

Index of the field.

@DATA_LABEL

nvarchar(150)

Terminology name used for the label.

@DATA_FIELD

nvarchar(100)

Field name.

@DATA_REQUIRED

bit

Required field flag.

@FORMAT_TAB_INDEX

int

HTML tab index.

@FORMAT_MAX_LENGTH

int

HTML maximum length for textbox.

@FORMAT_SIZE

int

HTML size of the textbox.

@COLSPAN

int

HTML column span.

 


Create the Data Scripts for the DETAILVIEWS_FIELDS Table

 

if not exists(select * from DETAILVIEWS_FIELDS where DETAIL_NAME = 'Teams.DetailView' and DELETED = 0) begin -- then

          print 'DETAILVIEWS_FIELDS Teams.DetailView';

          exec dbo.spDETAILVIEWS_InsertOnly          'Teams.DetailView', 'Teams', 'vwTEAMS_Edit', '15%', '35%', null;

          exec dbo.spDETAILVIEWS_FIELDS_InsBound     'Teams.DetailView',  0, 'Teams.LBL_NAME', 'NAME', '{0}', 3;

          exec dbo.spDETAILVIEWS_FIELDS_InsertOnly   'Teams.DetailView',  1, 'TextBox', 'Teams.LBL_DESCRIPTION', 'DESCRIPTION', null, null, null, null, null, 3, null;

end -- if;

 

The following is the definition of each field in the spDETAILVIEWS_InsertOnly stored procedure:

@NAME

nvarchar(50)

Name for the detail view.

@MODULE_NAME

nvarchar(25)

Module that this view applies to.

@VIEW_NAME

nvarchar(50)

SQL view for the edit view.

@LABEL_WIDTH

nvarchar(10)

Width of the label.  Typically 15%.

@FIELD_WIDTH

nvarchar(10)

Width of the field.  Typically 35%.

@DATA_COLUMNS

int

Number of data columns.  Typically 2.

 

The following is the definition of each field in the spDETAILVIEWS_FIELDS_InsBound stored procedure:

@DETAIL_NAME

nvarchar(50)

Name of the detail view.

@FIELD_INDEX

int

Index of the field.

@DATA_LABEL

nvarchar(150)

Terminology name used for the label.

@DATA_FIELD

nvarchar(100)

Field name.

@DATA_FORMAT

nvarchar(100)

Display format.  Uses ASP.NET formatting rules, such as {0}, {1} and {0:c}.

@COLSPAN

int

HTML column span.

 

The following is the definition of each field in the spDETAILVIEWS_FIELDS_InsertOnly stored procedure:

@DETAIL_NAME

nvarchar(50)

Name of the detail view.

@FIELD_INDEX

int

Index of the field.

@FIELD_TYPE

nvarchar(25)

 

@DATA_LABEL

nvarchar(150)

Terminology name used for the label.

@DATA_FIELD

nvarchar(100)

Field name.

@DATA_FORMAT

nvarchar(100)

Display format.  Uses ASP.NET formatting rules, such as {0}, {1} and {0:c}.

@URL_FIELD

nvarchar(50)

Field used in the URL.

@URL_FORMAT

nvarchar(100)

Format for the URL with {0} style replacements.

@URL_TARGET

nvarchar(20)

HTML target for the URL.

@LIST_NAME

nvarchar(50)

List name.

@COLSPAN

Int

HTML column span.

@TOOL_TIP

nvarchar(150)

Terminology name used for the tool tip.

 

 


Create the data scripts for the DYNAMIC_BUTTONS table.

 

exec dbo.spDYNAMIC_BUTTONS_CopyDefault '.DetailView', 'Teams.DetailView', 'Teams';

exec dbo.spDYNAMIC_BUTTONS_CopyDefault '.EditView'  , 'Teams.EditView'  , 'Teams';

 

The following is the definition of each field in the spDYNAMIC_BUTTONS_CopyDefault stored procedure:

@SOURCE_VIEW_NAME

nvarchar(50)

Source name.

@NEW_VIEW_NAME

nvarchar(50)

Destination name.

@MODULE_NAME

nvarchar(25)

Destination module.

 


Create the data scripts for the DETAILVIEW_RELATIONSHIPS table

 

if not exists(select * from DETAILVIEWS_RELATIONSHIPS where DETAIL_NAME = 'Teams.DetailView' and DELETED = 0) begin -- then

          print 'DETAILVIEWS_RELATIONSHIPS Teams.DetailView Professional';

          exec dbo.spDETAILVIEWS_RELATIONSHIPS_InsertOnly 'Teams.DetailView', 'Users', 'Users',  0, 'Users.LBL_MODULE_NAME';

end -- if;

 

The following is the definition of each field in the spDETAILVIEWS_RELATIONSHIPS_InsertOnly stored procedure:

@DETAIL_NAME

nvarchar(50)

Name of the detail view.

@MODULE_NAME

nvarchar(50)

Module that this relationship belongs to so that access rights can be applied.

@CONTROL_NAME

nvarchar(50)

Name of the control, without the .ascx file extension.

@RELATIONSHIP_ORDER

int

Order of the relationship panel.

@TITLE

nvarchar(100)

Terminology name for the panel.  We do not currently display this value.

 


Create the ASP.NET Code

 

Create the ListView Code

default.aspx

<%@ Page language="c#" MasterPageFile="~/DefaultView.Master" Codebehind="default.aspx.cs" AutoEventWireup="false" Inherits="SplendidCRM.Administration.Teams.Default" %>

          <%@ Register TagPrefix="SplendidCRM" Tagname="Shortcuts" Src="/portals/0/~/_controls/Shortcuts.ascx" %>

         

 

          <%@ Register TagPrefix="SplendidCRM" Tagname="ListView" Src="/portals/0/ListView.ascx" %>

         

         

 

default.aspx.cs

using System;

using System.Data;

using System.Data.Common;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Diagnostics;

 

namespace SplendidCRM.Administration.Teams

{

          ///

          /// Summary description for Default.

          ///

          public class Default : SplendidAdminPage

          {

                   private void Page_Load(object sender, System.EventArgs e)

                   {

                   }

 

                   #region Web Form Designer generated code

                   override protected void OnInit(EventArgs e)

                   {

                             //

                             // CODEGEN: This call is required by the ASP.NET Web Form Designer.

                             //

                             InitializeComponent();

                             base.OnInit(e);

                   }

                  

                   ///

                   /// Required method for Designer support - do not modify

                   /// the contents of this method with the code editor.

                   ///

                   private void InitializeComponent()

                   {   

                             this.IsAdminPage = true;

                             this.Load += new System.EventHandler(this.Page_Load);

                   }

                   #endregion

          }

}

 

ListView.ascx

<%@ Control CodeBehind="ListView.ascx.cs" Language="c#" AutoEventWireup="false" Inherits="SplendidCRM.Administration.Teams.ListView" %>

          <%@ Register TagPrefix="SplendidCRM" Tagname="ModuleHeader" Src="/portals/0/~/_controls/ModuleHeader.ascx" %>

         

         

         

          <%@ Register TagPrefix="SplendidCRM" Tagname="ListHeader" Src="/portals/0/~/_controls/ListHeader.ascx" %>

         

         

         

                  

         

         

         

                  

                            

                                     

                                                " />

                                     

                            

                            

                                     

                                                ')">

                                                         

                                                            CommandName="Teams.Delete" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "ID") %>' OnCommand="Page_Command" CssClass="listViewTdToolsS1" Text='<%# L10n.Term(".LNK_DELETE") %>' Runat="server" />

                                               

                                     

                            

                  

         

          <%@ Register TagPrefix="SplendidCRM" Tagname="CheckAll" Src="/portals/0/~/_controls/CheckAll.ascx" %>

         

          <%@ Register TagPrefix="SplendidCRM" Tagname="MassUpdate" Src="/portals/0/MassUpdate.ascx" %>

         

 

          <%@ Register TagPrefix="SplendidCRM" Tagname="DumpSQL" Src="/portals/0/~/_controls/DumpSQL.ascx" %>

         

 

ListView.ascx.cs

using System;

using System.Data;

using System.Data.Common;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Diagnostics;

//using Microsoft.VisualBasic;

 

namespace SplendidCRM.Administration.Teams

{

          ///

          ///                Summary description for ListView.

          ///

          public class ListView : SplendidControl

          {

                   protected DataView      vwMain         ;

                   protected SplendidGrid  grdMain        ;

                   protected Label         lblError       ;

                   protected PlaceHolder   plcSearch      ;

                   protected SearchControl ctlSearch      ;

                   protected MassUpdate    ctlMassUpdate  ;

 

                   protected void Page_Command(object sender, CommandEventArgs e)

                   {

                             try

                             {

                                      if ( e.CommandName == "Clear" )

                                      {

                                                ctlSearch.ClearForm();

                                                Server.Transfer("default.aspx");

                                      }

                                      else if ( e.CommandName == "Search" )

                                      {

                                                // 10/13/2005 Paul.  Make sure to clear the page index prior to applying search.

                                                grdMain.CurrentPageIndex = 0;

                                                grdMain.ApplySort();

                                                grdMain.DataBind();

                                      }

                                      else if ( e.CommandName == "Teams.Delete" )

                                      {

                                                Guid gID = Sql.ToGuid(e.CommandArgument);

                                                SqlProcs.spTEAMS_Delete(gID);

                                                grdMain.CurrentPageIndex = 0;

                                                grdMain.ApplySort();

                                                grdMain.DataBind();

                                                Response.Redirect("default.aspx");

                                      }

                                      else if ( e.CommandName == "MassDelete" )

                                      {

                                                string[] arrID = Request.Form.GetValues("chkMain");

                                                if ( arrID != null )

                                                {

                                                          string sIDs = Utils.ValidateIDs(arrID);

                                                          if ( !Sql.IsEmptyString(sIDs) )

                                                          {

                                                                   SqlProcs.spTEAMS_MassDelete(sIDs);

                                                                   Response.Redirect("default.aspx");

                                                          }

                                                }

                                      }

                             }

                             catch(Exception ex)

                             {

                                      SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                      lblError.Text = ex.Message;

                             }

                   }

 

                   private void Page_Load(object sender, System.EventArgs e)

                   {

                             SetPageTitle(L10n.Term(m_sMODULE + ".LBL_LIST_FORM_TITLE"));

                             // 06/04/2006 Paul.  Visibility is already controlled by the ASPX page, but it is probably a good idea to skip the load.

                             this.Visible = SplendidCRM.Security.IS_ADMIN;

                             if ( !this.Visible )

                                      return;

 

                             try

                             {

                                      DbProviderFactory dbf = DbProviderFactories.GetFactory();

                                      using ( IDbConnection con = dbf.CreateConnection() )

                                      {

                                                string sSQL;

                                                sSQL = "select *           " + ControlChars.CrLf

                                                     + "  from vwTEAMS_List" + ControlChars.CrLf

                                                     + " where 1 = 1       " + ControlChars.CrLf;

                                                using ( IDbCommand cmd = con.CreateCommand() )

                                                {

                                                          cmd.CommandText = sSQL;

                                                          ctlSearch.SqlSearchClause(cmd);

 

                                                          if ( bDebug )

                                                                   RegisterClientScriptBlock("SQLCode", Sql.ClientScriptBlock(cmd));

 

                                                          using ( DbDataAdapter da = dbf.CreateDataAdapter() )

                                                          {

                                                                   ((IDbDataAdapter)da).SelectCommand = cmd;

                                                                   using ( DataTable dt = new DataTable() )

                                                                   {

                                                                             da.Fill(dt);

                                                                             vwMain = dt.DefaultView;

                                                                             grdMain.DataSource = vwMain ;

                                                                             if ( !IsPostBack )

                                                                             {

                                                                                      if ( String.IsNullOrEmpty(grdMain.SortColumn) )

                                                                                      {

                                                                                                grdMain.SortColumn = "NAME";

                                                                                                grdMain.SortOrder  = "asc" ;

                                                                                      }

                                                                                      grdMain.ApplySort();

                                                                                      grdMain.DataBind();

                                                                             }

                                                                   }

                                                          }

                                                }

                                      }

                             }

                             catch(Exception ex)

                             {

                                      SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                      lblError.Text = ex.Message;

                             }

                             if ( !IsPostBack )

                             {

                                      // 06/09/2006 Paul.  Remove data binding in the user controls.  Binding is required, but only do so in the ASPX pages.

                                      //Page.DataBind();

                             }

                   }

 

                   #region Web Form Designer generated code

                   override protected void OnInit(EventArgs e)

                   {

                             //

                             // CODEGEN: This call is required by the ASP.NET Web Form Designer.

                             //

                             InitializeComponent();

                             base.OnInit(e);

                   }

                  

                   ///

                   ///                Required method for Designer support - do not modify

                   ///                the contents of this method with the code editor.

                   ///

                   private void InitializeComponent()

                   {

                             this.Load += new System.EventHandler(this.Page_Load);

                             m_sMODULE = "Teams";

                             SetMenu(m_sMODULE);

                             this.AppendGridColumns(grdMain, m_sMODULE + ".ListView");

                             // We have to load the control in here, otherwise the control will not initialized before the Page_Load above.

                             ctlSearch = (SearchControl) LoadControl("SearchBasic.ascx");

                             plcSearch.Controls.Add(ctlSearch);

                             ctlSearch.Command = new CommandEventHandler(Page_Command);

                             ctlMassUpdate.Command = new CommandEventHandler(Page_Command);

                   }

                   #endregion

          }

}

 

 


Create the EditView Code

edit.aspx

<%@ Page language="c#" MasterPageFile="~/DefaultView.Master" Codebehind="edit.aspx.cs" AutoEventWireup="false" Inherits="SplendidCRM.Administration.Teams.Edit" %>

          <%@ Register TagPrefix="SplendidCRM" Tagname="Shortcuts" Src="/portals/0/~/_controls/Shortcuts.ascx" %>

         

 

          <%@ Register TagPrefix="SplendidCRM" Tagname="EditView" Src="/portals/0/EditView.ascx" %>

         

         

 

edit.aspx.cs

using System;

using System.Data;

using System.Data.Common;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Diagnostics;

 

namespace SplendidCRM.Administration.Teams

{

          ///

          /// Summary description for Edit.

          ///

          public class Edit : SplendidAdminPage

          {

                   private void Page_Load(object sender, System.EventArgs e)

                   {

                   }

 

                   #region Web Form Designer generated code

                   override protected void OnInit(EventArgs e)

                   {

                             //

                             // CODEGEN: This call is required by the ASP.NET Web Form Designer.

                             //

                             InitializeComponent();

                             base.OnInit(e);

                   }

                  

                   ///

                   /// Required method for Designer support - do not modify

                   /// the contents of this method with the code editor.

                   ///

                   private void InitializeComponent()

                   {   

                             this.IsAdminPage = true;

                             this.Load += new System.EventHandler(this.Page_Load);

                   }

                   #endregion

          }

}

 

EditView.ascx

<%@ Control Language="c#" AutoEventWireup="false" Codebehind="EditView.ascx.cs" Inherits="SplendidCRM.Administration.Teams.EditView" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>

          <%@ Register TagPrefix="SplendidCRM" Tagname="ModuleHeader" Src="/portals/0/~/_controls/ModuleHeader.ascx" %>

         

         

          <%@ Register TagPrefix="SplendidCRM" Tagname="DynamicButtons" Src="/portals/0/~/_controls/DynamicButtons.ascx" %>

         

         

                  

                            

                                     

                                     

                            

                  

         

         

 

EditView.ascx.cs

using System;

using System.Data;

using System.Data.Common;

using System.Drawing;

using System.Web;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Diagnostics;

 

namespace SplendidCRM.Administration.Teams

{

          ///

          ///                Summary description for EditView.

          ///

          public class EditView : SplendidControl

          {

                   protected _controls.ModuleHeader   ctlModuleHeader  ;

                   protected _controls.DynamicButtons ctlDynamicButtons;

 

                   protected Guid            gID                          ;

                   protected HtmlTable       tblMain                      ;

 

                   protected void Page_Command(Object sender, CommandEventArgs e)

                   {

                             if ( e.CommandName == "Save" )

                             {

                                      try

                                      {

                                                // 01/16/2006 Paul.  Enable validator before validating page.

                                                this.ValidateEditViewFields(m_sMODULE + ".EditView");

                                                if ( Page.IsValid )

                                                {

                                                          DbProviderFactory dbf = DbProviderFactories.GetFactory();

                                                          using ( IDbConnection con = dbf.CreateConnection() )

                                                          {

                                                                   con.Open();

                                                                   string sSQL;

                                                                   string sCUSTOM_MODULE = "TEAMS";

                                                                   DataTable dtCustomFields = SplendidCache.FieldsMetaData_Validated(sCUSTOM_MODULE);

                                                                   using ( IDbTransaction trn = con.BeginTransaction() )

                                                                   {

                                                                             try

                                                                             {

                                                                                      SqlProcs.spTEAMS_Update

                                                                                                ( ref gID

                                                                                                , new DynamicControl(this, "NAME"       ).Text

                                                                                                , new DynamicControl(this, "DESCRIPTION").Text

                                                                                                , trn

                                                                                                );

                                                                                      SplendidDynamic.UpdateCustomFields(this, trn, gID, sCUSTOM_MODULE, dtCustomFields);

                                                                                     

                                                                                      trn.Commit();

                                                                             }

                                                                             catch(Exception ex)

                                                                             {

                                                                                      trn.Rollback();

                                                                                      SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                                                                      ctlDynamicButtons.ErrorText = ex.Message;

                                                                                      return;

                                                                             }

                                                                   }

                                                          }

                                                          Response.Redirect("view.aspx?ID=" + gID.ToString());

                                                }

                                      }

                                      catch(Exception ex)

                                      {

                                                SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                                ctlDynamicButtons.ErrorText = ex.Message;

                                      }

                             }

                             else if ( e.CommandName == "Cancel" )

                             {

                                      if ( Sql.IsEmptyGuid(gID) )

                                                Response.Redirect("default.aspx");

                                      else

                                                Response.Redirect("view.aspx?ID=" + gID.ToString());

                             }

                   }

 

                   private void Page_Load(object sender, System.EventArgs e)

                   {

                             SetPageTitle(L10n.Term(m_sMODULE + ".LBL_LIST_FORM_TITLE"));

                             // 06/04/2006 Paul.  Visibility is already controlled by the ASPX page, but it is probably a good idea to skip the load.

                             this.Visible = SplendidCRM.Security.IS_ADMIN;

                             if ( !this.Visible )

                                      return;

 

                             try

                             {

                                      gID = Sql.ToGuid(Request["ID"]);

                                      if ( !IsPostBack )

                                      {

                                                // 03/20/2008 Paul.  Dynamic buttons need to be recreated in order for events to fire.

                                                ctlDynamicButtons.AppendButtons(m_sMODULE + ".EditView", Guid.Empty, null);

 

                                                Guid gDuplicateID = Sql.ToGuid(Request["DuplicateID"]);

                                                if ( !Sql.IsEmptyGuid(gID) || !Sql.IsEmptyGuid(gDuplicateID) )

                                                {

                                                          DbProviderFactory dbf = DbProviderFactories.GetFactory();

                                                          using ( IDbConnection con = dbf.CreateConnection() )

                                                          {

                                                                   string sSQL ;

                                                                   sSQL = "select *           " + ControlChars.CrLf

                                                                        + "  from vwTEAMS_Edit" + ControlChars.CrLf

                                                                        + " where ID = @ID    " + ControlChars.CrLf;

                                                                   using ( IDbCommand cmd = con.CreateCommand() )

                                                                   {

                                                                             cmd.CommandText = sSQL;

                                                                             if ( !Sql.IsEmptyGuid(gDuplicateID) )

                                                                             {

                                                                                      Sql.AddParameter(cmd, "@ID", gDuplicateID);

                                                                                       gID = Guid.Empty;

                                                                             }

                                                                             else

                                                                             {

                                                                                      Sql.AddParameter(cmd, "@ID", gID);

                                                                             }

                                                                             con.Open();

 

                                                                             if ( bDebug )

                                                                                      RegisterClientScriptBlock("SQLCode", Sql.ClientScriptBlock(cmd));

 

                                                                             using ( IDataReader rdr = cmd.ExecuteReader(CommandBehavior.SingleRow) )

                                                                             {

                                                                                      if ( rdr.Read() )

                                                                                      {

                                                                                                ctlModuleHeader.Title = Sql.ToString(rdr["NAME"]);

                                                                                                SetPageTitle(L10n.Term(".moduleList." + m_sMODULE) + " - " + ctlModuleHeader.Title);

                                                                                                ViewState["ctlModuleHeader.Title"] = ctlModuleHeader.Title;

 

                                                                                                this.AppendEditViewFields(m_sMODULE + ".EditView", tblMain, rdr);

                                                                                      }

                                                                             }

                                                                   }

                                                          }

                                                }

                                                else

                                                {

                                                          this.AppendEditViewFields(m_sMODULE + ".EditView", tblMain, null);

                                                }

                                      }

                                      else

                                      {

                                                // 12/02/2005 Paul.  When validation fails, the header title does not retain its value.  Update manually.

                                                ctlModuleHeader.Title = Sql.ToString(ViewState["ctlModuleHeader.Title"]);

                                                SetPageTitle(L10n.Term(".moduleList." + m_sMODULE) + " - " + ctlModuleHeader.Title);

                                      }

                             }

                             catch(Exception ex)

                             {

                                      SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                      ctlDynamicButtons.ErrorText = ex.Message;

                             }

                   }

 

                   #region Web Form Designer generated code

                   override protected void OnInit(EventArgs e)

                   {

                             //

                             // CODEGEN: This Task is required by the ASP.NET Web Form Designer.

                             //

                             InitializeComponent();

                             base.OnInit(e);

                   }

                  

                   ///

                   ///                Required method for Designer support - do not modify

                   ///                the contents of this method with the code editor.

                   ///

                   private void InitializeComponent()

                   {

                             this.Load += new System.EventHandler(this.Page_Load);

                             ctlDynamicButtons.Command += new CommandEventHandler(Page_Command);

                             m_sMODULE = "Teams";

                             SetMenu(m_sMODULE);

                             if ( IsPostBack )

                             {

                                      // 12/02/2005 Paul.  Need to add the edit fields in order for events to fire.

                                      this.AppendEditViewFields(m_sMODULE + ".EditView", tblMain, null);

                                      // 03/20/2008 Paul.  Dynamic buttons need to be recreated in order for events to fire.

                                      ctlDynamicButtons.AppendButtons(m_sMODULE + ".EditView", Guid.Empty, null);

                             }

                   }

                   #endregion

          }

}

 


Create the DetailView Code

view.aspx

<%@ Page language="c#" MasterPageFile="~/DefaultView.Master" Codebehind="view.aspx.cs" AutoEventWireup="false" Inherits="SplendidCRM.Administration.Teams.View" %>

          <%@ Register TagPrefix="SplendidCRM" Tagname="Shortcuts" Src="/portals/0/~/_controls/Shortcuts.ascx" %>

         

 

          <%@ Register TagPrefix="SplendidCRM" Tagname="DetailView" Src="/portals/0/DetailView.ascx" %>

         

         

 

view.aspx.cs

using System;

using System.Data;

using System.Data.Common;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Diagnostics;

 

namespace SplendidCRM.Administration.Teams

{

          ///

          /// Summary description for View.

          ///

          public class View : SplendidAdminPage

          {

                   private void Page_Load(object sender, System.EventArgs e)

                   {

                             if ( !IsPostBack )

                             {

                                      // 03/11/2008 Paul.  Move the primary binding to SplendidPage.

                                      //Page DataBind();

                             }

                   }

 

                   #region Web Form Designer generated code

                   override protected void OnInit(EventArgs e)

                   {

                             //

                             // CODEGEN: This call is required by the ASP.NET Web Form Designer.

                             //

                             InitializeComponent();

                             base.OnInit(e);

                   }

                  

                   ///

                   /// Required method for Designer support - do not modify

                   /// the contents of this method with the code editor.

                   ///

                   private void InitializeComponent()

                   {   

                             this.IsAdminPage = true;

                             this.Load += new System.EventHandler(this.Page_Load);

                   }

                   #endregion

          }

}

 

DetailView.aspx

<%@ Control Language="c#" AutoEventWireup="false" Codebehind="DetailView.ascx.cs" Inherits="SplendidCRM.Administration.Teams.DetailView" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>

          <%@ Register TagPrefix="SplendidCRM" Tagname="ModuleHeader" Src="/portals/0/~/_controls/ModuleHeader.ascx" %>

         

 

          <%@ Register TagPrefix="SplendidCRM" Tagname="DynamicButtons" Src="/portals/0/~/_controls/DynamicButtons.ascx" %>

         

 

         

         

         

         

         

                  

         

 

<%@ Register TagPrefix="SplendidCRM" Tagname="DumpSQL" Src="/portals/0/~/_controls/DumpSQL.ascx" %>

 

DetailView.aspx.cs

using System;

using System.Data;

using System.Data.Common;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Diagnostics;

 

namespace SplendidCRM.Administration.Teams

{

          ///

          /// Summary description for DetailView.

          ///

          public class DetailView : SplendidControl

          {

                   protected _controls.ModuleHeader  ctlModuleHeader ;

                   protected _controls.DynamicButtons ctlDynamicButtons;

 

                   protected Guid        gID              ;

                   protected HtmlTable   tblMain          ;

                   protected PlaceHolder plcSubPanel;

 

                   protected void Page_Command(Object sender, CommandEventArgs e)

                   {

                             try

                             {

                                      if ( e.CommandName == "Edit" )

                                      {

                                                Response.Redirect("edit.aspx?ID=" + gID.ToString());

                                      }

                                      else if ( e.CommandName == "Duplicate" )

                                      {

                                                Response.Redirect("edit.aspx?DuplicateID=" + gID.ToString());

                                      }

                                      else if ( e.CommandName == "Delete" )

                                      {

                                                SqlProcs.spTEAMS_Delete(gID);

                                                Response.Redirect("default.aspx");

                                      }

                             }

                             catch(Exception ex)

                             {

                                      SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                      ctlDynamicButtons.ErrorText = ex.Message;

                             }

                   }

 

                   private void Page_Load(object sender, System.EventArgs e)

                   {

                             SetPageTitle(L10n.Term(m_sMODULE + ".LBL_TEAMS"));

                             // 06/04/2006 Paul.  Visibility is already controlled by the ASPX page, but it is probably a good idea to skip the load.

                             this.Visible = SplendidCRM.Security.IS_ADMIN;

                             if ( !this.Visible )

                                      return;

 

                             try

                             {

                                      gID = Sql.ToGuid(Request["ID"]);

                                      // 11/28/2005 Paul.  We must always populate the table, otherwise it will disappear during event processing.

                                      // 03/19/2008 Paul.  Place AppendDetailViewFields inside OnInit to avoid having to re-populate the data.

                                      if ( !IsPostBack )

                                      {

                                                if ( !Sql.IsEmptyGuid(gID) )

                                                {

                                                          DbProviderFactory dbf = DbProviderFactories.GetFactory();

                                                          using ( IDbConnection con = dbf.CreateConnection() )

                                                          {

                                                                   string sSQL ;

                                                                   sSQL = "select *           " + ControlChars.CrLf

                                                                        + "  from vwTEAMS_Edit" + ControlChars.CrLf

                                                                        + " where ID = @ID    " + ControlChars.CrLf;

                                                                   using ( IDbCommand cmd = con.CreateCommand() )

                                                                   {

                                                                             cmd.CommandText = sSQL;

                                                                             Sql.AddParameter(cmd, "@ID", gID);

                                                                             con.Open();

 

                                                                             if ( bDebug )

                                                                                      RegisterClientScriptBlock("SQLCode", Sql.ClientScriptBlock(cmd));

 

                                                                             using ( IDataReader rdr = cmd.ExecuteReader(CommandBehavior.SingleRow) )

                                                                             {

                                                                                      if ( rdr.Read() )

                                                                                      {

                                                                                                ctlModuleHeader.Title = Sql.ToString(rdr["NAME"]);

                                                                                                SetPageTitle(L10n.Term(".moduleList." + m_sMODULE) + " - " + ctlModuleHeader.Title);

                                                                                               

                                                                                                this.AppendDetailViewFields(m_sMODULE + ".DetailView", tblMain, rdr);

                                                                                                // 03/20/2008 Paul.  Dynamic buttons need to be recreated in order for events to fire.

                                                                                                ctlDynamicButtons.AppendButtons(m_sMODULE + ".DetailView", Guid.Empty, rdr);

                                                                                      }

                                                                                      else

                                                                                      {

                                                                                                // 11/25/2006 Paul.  If item is not visible, then don't show its sub panel either.

                                                                                                plcSubPanel.Visible = false;

                                                                                               

                                                                                                // 03/20/2008 Paul.  Dynamic buttons need to be recreated in order for events to fire.

                                                                                                ctlDynamicButtons.AppendButtons(m_sMODULE + ".DetailView", Guid.Empty, null);

                                                                                                ctlDynamicButtons.DisableAll();

                                                                                                ctlDynamicButtons.ErrorText = L10n.Term("ACL.LBL_NO_ACCESS");

                                                                                      }

                                                                             }

                                                                   }

                                                          }

                                                }

                                                else

                                                {

                                                          // 03/20/2008 Paul.  Dynamic buttons need to be recreated in order for events to fire.

                                                          ctlDynamicButtons.AppendButtons(m_sMODULE + ".DetailView", Guid.Empty, null);

                                                          ctlDynamicButtons.DisableAll();

                                                          //ctlDynamicButtons.ErrorText = L10n.Term(".ERR_MISSING_REQUIRED_FIELDS") + "ID";

                                                }

                                      }

                                      // 06/09/2006 Paul.  Remove data binding in the user controls.  Binding is required, but only do so in the ASPX pages.

                                      //Page.DataBind();

                             }

                             catch(Exception ex)

                             {

                                      SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                      ctlDynamicButtons.ErrorText = ex.Message;

                             }

                   }

 

                   #region Web Form Designer generated code

                   override protected void OnInit(EventArgs e)

                   {

                             //

                             // CODEGEN: This call is required by the ASP.NET Web Form Designer.

                             //

                             InitializeComponent();

                             base.OnInit(e);

                   }

                  

                   ///

                   /// Required method for Designer support - do not modify

                   /// the contents of this method with the code editor.

                   ///

                   private void InitializeComponent()

                   {   

                             this.Load += new System.EventHandler(this.Page_Load);

                             ctlDynamicButtons.Command += new CommandEventHandler(Page_Command);

                             m_sMODULE = "Teams";

                             SetMenu(m_sMODULE);

                             this.AppendDetailViewRelationships(m_sMODULE + ".DetailView", plcSubPanel);

                             if ( IsPostBack )

                             {

                                      this.AppendDetailViewFields(m_sMODULE + ".DetailView", tblMain, null);

                                      // 03/20/2008 Paul.  Dynamic buttons need to be recreated in order for events to fire.

                                      ctlDynamicButtons.AppendButtons(m_sMODULE + ".DetailView", Guid.Empty, null);

                             }

                   }

                   #endregion

          }

}

 


Create the PopupView Code

Popup.aspx

<%@ Page language="c#" MasterPageFile="~/PopupView.Master" Codebehind="Popup.aspx.cs" AutoEventWireup="false" Inherits="SplendidCRM.Administration.Teams.Popup" %>

          <%@ Register TagPrefix="SplendidCRM" Tagname="PopupView" Src="/portals/0/PopupView.ascx" %>

         

         

 

Popup.aspx.cs

using System;

using System.Data;

using System.Data.Common;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Diagnostics;

 

namespace SplendidCRM.Administration.Teams

{

          ///

          /// Summary description for Popup.

          ///

          public class Popup : SplendidPopup

          {

                   private void Page_Load(object sender, System.EventArgs e)

                   {

                   }

 

                   #region Web Form Designer generated code

                   override protected void OnInit(EventArgs e)

                   {

                             //

                             // CODEGEN: This call is required by the ASP.NET Web Form Designer.

                             //

                             InitializeComponent();

                             base.OnInit(e);

                   }

                  

                   ///

                   /// Required method for Designer support - do not modify

                   /// the contents of this method with the code editor.

                   ///

                   private void InitializeComponent()

                   {   

                             this.Load += new System.EventHandler(this.Page_Load);

                   }

                   #endregion

          }

}

 

PopupView.ascx

<%@ Control CodeBehind="PopupView.ascx.cs" Language="c#" AutoEventWireup="false" Inherits="SplendidCRM.Administration.Teams.PopupView" %>

          <%@ Register TagPrefix="SplendidCRM" Tagname="SearchView" Src="/portals/0/~/_controls/SearchView.ascx" %>

         

 

         

          <%@ Register TagPrefix="SplendidCRM" Tagname="ListHeader" Src="/portals/0/~/_controls/ListHeader.ascx" %>

         

 

          <%@ Register TagPrefix="SplendidCRM" Tagname="DynamicButtons" Src="/portals/0/~/_controls/DynamicButtons.ascx" %>

         

 

         

                  

                            

                                     

                                               

                                                          " class="checkbox" type="checkbox" value="<%# DataBinder.Eval(Container.DataItem, "ID") %>" />

                                               

                                     

                            

                  

         

          <%@ Register TagPrefix="SplendidCRM" Tagname="CheckAll" Src="/portals/0/~/_controls/CheckAll.ascx" %>

         

 

          <%@ Register TagPrefix="SplendidCRM" Tagname="DumpSQL" Src="/portals/0/~/_controls/DumpSQL.ascx" %>

         

 

PopupView.ascx.cs

using System;

using System.Data;

using System.Data.Common;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Diagnostics;

 

namespace SplendidCRM.Administration.Teams

{

          ///

          ///                Summary description for PopupView.

          ///

          public class PopupView : SplendidControl

          {

                   protected SplendidCRM._controls.SearchView   ctlSearchView  ;

 

                   protected _controls.DynamicButtons ctlDynamicButtons;

                   protected UniqueStringCollection arrSelectFields;

                   protected DataView      vwMain         ;

                   protected SplendidGrid  grdMain        ;

                   protected bool          bMultiSelect   ;

 

                   public bool MultiSelect

                   {

                             get { return bMultiSelect; }

                             set { bMultiSelect = value; }

                   }

 

                   protected void Page_Command(object sender, CommandEventArgs e)

                   {

                             try

                             {

                                      if ( e.CommandName == "Search" )

                                      {

                                                // 10/13/2005 Paul.  Make sure to clear the page index prior to applying search.

                                                grdMain.CurrentPageIndex = 0;

                                                // 04/27/2008 Paul.  Sorting has been moved to the database to increase performance.

                                                grdMain.DataBind();

                                      }

                                      // 12/14/2007 Paul.  We need to capture the sort event from the SearchView.

                                      else if ( e.CommandName == "SortGrid" )

                                      {

                                                grdMain.SetSortFields(e.CommandArgument as string[]);

                                                // 04/27/2008 Paul.  Sorting has been moved to the database to increase performance.

                                                arrSelectFields.Add(grdMain.SortColumn);

                                      }

                             }

                             catch(Exception ex)

                             {

                                      SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                      ctlDynamicButtons.ErrorText = ex.Message;

                             }

                   }

 

                   private void Page_Load(object sender, System.EventArgs e)

                   {

                             SetPageTitle(L10n.Term(m_sMODULE + ".LBL_LIST_FORM_TITLE"));

                             // 07/05/2009 Paul.  We don't use access control on the team list as all users can assign a record to any team.

                             //this.Visible = (SplendidCRM.Security.GetUserAccess(m_sMODULE, "list") >= 0);

                             if ( !this.Visible )

                                      return;

 

                             try

                             {

                                      DbProviderFactory dbf = DbProviderFactories.GetFactory();

                                      using ( IDbConnection con = dbf.CreateConnection() )

                                      {

                                                string sSQL;

                                                // 11/25/2006 Paul.  An admin can see all teams, but most users will only see the teams which they are assigned to.

                                                if ( Security.IS_ADMIN )

                                                {

                                                          sSQL = "  from vwTEAMS_List" + ControlChars.CrLf

                                                               + " where 1 = 1       " + ControlChars.CrLf;

                                                }

                                                else

                                                {

                                                          sSQL = "  from vwTEAMS_MyList" + ControlChars.CrLf

                                                               + " where MEMBERSHIP_USER_ID = @MEMBERSHIP_USER_ID" + ControlChars.CrLf;

                                                }

                                                using ( IDbCommand cmd = con.CreateCommand() )

                                                {

                                                          cmd.CommandText = sSQL;

                                                          if ( !Security.IS_ADMIN )

                                                                   Sql.AddParameter(cmd, "@MEMBERSHIP_USER_ID", Security.USER_ID);

                                                          // 04/27/2008 Paul.  A ListView will need to set and build the order clause in two setps

                                                          // so that the SavedSearch sort value can be taken into account.

                                                          grdMain.OrderByClause("NAME", "asc");

                                                          ctlSearchView.SqlSearchClause(cmd);

                                                          // 04/27/2008 Paul.  The fields in the search clause need to be prepended after any Saved Search sort has been determined.

                                                          cmd.CommandText = "select " + Sql.FormatSelectFields(arrSelectFields)

                                                                          + cmd.CommandText

                                                                          + grdMain.OrderByClause();

 

                                                          if ( bDebug )

                                                                   Page.ClientScript.RegisterClientScriptBlock(System.Type.GetType("System.String"), "SQLCode", Sql.ClientScriptBlock(cmd));

 

                                                          using ( DbDataAdapter da = dbf.CreateDataAdapter() )

                                                          {

                                                                   ((IDbDataAdapter)da).SelectCommand = cmd;

                                                                   using ( DataTable dt = new DataTable() )

                                                                   {

                                                                             da.Fill(dt);

                                                                             vwMain = dt.DefaultView;

                                                                             grdMain.DataSource = vwMain ;

                                                                             if ( !IsPostBack )

                                                                             {

                                                                                      grdMain.DataBind();

                                                                             }

                                                                   }

                                                          }

                                                }

                                      }

                             }

                             catch(Exception ex)

                             {

                                      SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                      ctlDynamicButtons.ErrorText = ex.Message;

                             }

                             if ( !IsPostBack )

                             {

                                      // 03/11/2008 Paul.  Move the primary binding to SplendidPage.

                                      //Page DataBind();

                             }

                   }

 

                   #region Web Form Designer generated code

                   override protected void OnInit(EventArgs e)

                   {

                             //

                             // CODEGEN: This call is required by the ASP.NET Web Form Designer.

                             //

                             InitializeComponent();

                             base.OnInit(e);

                   }

                  

                   ///

                   /// Required method for Designer support - do not modify

                   /// the contents of this method with the code editor.

                   ///

                   private void InitializeComponent()

                   {   

                             this.Load += new System.EventHandler(this.Page_Load);

                             ctlDynamicButtons.Command += new CommandEventHandler(Page_Command);

                             ctlSearchView.Command = new CommandEventHandler(Page_Command);

                             m_sMODULE = "Teams";

                             arrSelectFields = new UniqueStringCollection();

                             arrSelectFields.Add("NAME");

                             this.AppendGridColumns(grdMain, m_sMODULE + ".PopupView", arrSelectFields);

                             ctlDynamicButtons.AppendButtons(m_sMODULE + ".Popup" + (bMultiSelect ? "MultiSelect" : "View"), Guid.Empty, Guid.Empty);

                             if ( !IsPostBack && !bMultiSelect )

                                      ctlDynamicButtons.ShowButton("Clear", !Sql.ToBoolean(Request["ClearDisabled"]));

                   }

                   #endregion

          }

}

 


Create the Relationship Controls

Users.ascx

<%@ Control CodeBehind="Users.ascx.cs" Language="c#" AutoEventWireup="false" Inherits="SplendidCRM.Administration.Teams.Users" %>

         

         

          <%@ Register TagPrefix="SplendidCRM" Tagname="ListHeader" Src="/portals/0/~/_controls/ListHeader.ascx" %>

         

         

          <%@ Register TagPrefix="SplendidCRM" Tagname="DynamicButtons" Src="/portals/0/~/_controls/DynamicButtons.ascx" %>

         

 

         

                  

                                    DataTextField="FULL_NAME" SortExpression="FULL_NAME"  ItemStyle-Width="18%" ItemStyle-CssClass="listViewTdLinkS1" DataNavigateUrlField="USER_ID" DataNavigateUrlFormatString="~/Users/view.aspx?id={0}" />

                                  HeaderText="Users.LBL_LIST_USER_NAME"  DataField="USER_NAME"     SortExpression="USER_NAME"  ItemStyle-Width="18%" />

                                  HeaderText="Teams.LBL_LIST_MEMBERSHIP" DataField="MEMBERSHIP"    SortExpression="MEMBERSHIP" ItemStyle-Width="18%" />

                                  HeaderText="Users.LBL_LIST_EMAIL"      DataField="EMAIL1"        SortExpression="EMAIL1"     ItemStyle-Width="18%" />

                                  HeaderText=".LBL_LIST_PHONE"           DataField="PHONE_WORK"    SortExpression="PHONE_WORK" ItemStyle-Width="15%" ItemStyle-Wrap="false" />

                               HeaderText="" ItemStyle-Width="1%" ItemStyle-HorizontalAlign="Left" ItemStyle-Wrap="false">

                                     

                                               

">

                                               

                                                  CommandName="Users.Remove" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "USER_ID") %>' OnCommand="Page_Command" CssClass="listViewTdToolsS1" Text='<%# L10n.Term(".LNK_REMOVE") %>' Runat="server" />

                                               

                                     

                            

                  

         

 

Users.ascx.cs

using System;

using System.Data;

using System.Data.Common;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Diagnostics;

 

namespace SplendidCRM.Administration.Teams

{

          ///

          ///                Summary description for Users.

          ///

          public class Users : SplendidControl

          {

                   protected _controls.DynamicButtons ctlDynamicButtons;

                   protected UniqueStringCollection arrSelectFields;

                   protected Guid            gID            ;

                   protected DataView        vwMain         ;

                   protected SplendidGrid    grdMain        ;

                   protected Label           lblError       ;

                   protected HtmlInputHidden txtUSER_ID     ;

 

                   protected void Page_Command(object sender, CommandEventArgs e)

                   {

                             try

                             {

                                      switch ( e.CommandName )

                                      {

                                                case "Users.Remove":

                                                {

                                                          Guid gUSER_ID = Sql.ToGuid(e.CommandArgument);

                                                          SqlProcs.spTEAM_MEMBERSHIPS_Delete(gID, gUSER_ID);

                                                          //Response.Redirect("view.aspx?ID=" + gID.ToString());

                                                          // 05/16/2008 Paul.  Instead of redirecting, just rebind the grid and AJAX will repaint.

                                                          BindGrid();

                                                          break;

                                                }

                                                default:

                                                          throw(new Exception("Unknown command: " + e.CommandName));

                                      }

                             }

                             catch(Exception ex)

                             {

                                      SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                      ctlDynamicButtons.ErrorText = ex.Message;

                             }

                   }

 

                   protected void BindGrid()

                   {

                             DbProviderFactory dbf = DbProviderFactories.GetFactory();

                             using ( IDbConnection con = dbf.CreateConnection() )

                             {

                                      string sSQL;

                                      sSQL = "select " + Sql.FormatSelectFields(arrSelectFields)

                                           + "  from vwTEAM_MEMBERSHIPS_List" + ControlChars.CrLf

                                           + " where 1 = 1                  " + ControlChars.CrLf;

                                      using ( IDbCommand cmd = con.CreateCommand() )

                                      {

                                                cmd.CommandText = sSQL;

                                                Sql.AppendParameter(cmd, gID, "TEAM_ID");

                                                cmd.CommandText += grdMain.OrderByClause("FULL_NAME", "asc");

 

                                                if ( bDebug )

                                                          RegisterClientScriptBlock("vwTEAM_MEMBERSHIPS_List", Sql.ClientScriptBlock(cmd));

 

                                                try

                                                {

                                                          using ( DbDataAdapter da = dbf.CreateDataAdapter() )

                                                          {

                                                                   ((IDbDataAdapter)da).SelectCommand = cmd;

                                                                   using ( DataTable dt = new DataTable() )

                                                                   {

                                                                             da.Fill(dt);

                                                                             dt.Columns.Add("MEMBERSHIP");

                                                                             string sMember          = L10n.Term(".team_membership_dom.Member");

                                                                             string sMemberReportsTo = L10n.Term(".team_membership_dom.Member Reports-to");

                                                                             foreach ( DataRow row in dt.Rows )

                                                                             {

                                                                                      if ( Sql.ToBoolean(row["EXPLICIT_ASSIGN"]) )

                                                                                                row["MEMBERSHIP"] = sMember;

                                                                                      else

                                                                                                row["MEMBERSHIP"] = sMemberReportsTo;

                                                                             }

                                                                             vwMain = dt.DefaultView;

                                                                             grdMain.DataSource = vwMain ;

                                                                             grdMain.DataBind();

                                                                   }

                                                          }

                                                }

                                                catch(Exception ex)

                                                {

                                                          SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                                          ctlDynamicButtons.ErrorText = ex.Message;

                                                }

                                      }

                             }

                   }

 

                   private void Page_Load(object sender, System.EventArgs e)

                   {

                             gID = Sql.ToGuid(Request["ID"]);

                             if ( !Sql.IsEmptyString(txtUSER_ID.Value) )

                             {

                                      try

                                      {

                                                SqlProcs.spTEAM_MEMBERSHIPS_MassUpdate(gID, txtUSER_ID.Value);

                                                // 05/16/2008 Paul.  Instead of redirecting, just rebind the grid and AJAX will repaint.

                                                //Response.Redirect("view.aspx?ID=" + gID.ToString());

                                                txtUSER_ID.Value = String.Empty;

                                      }

                                      catch(Exception ex)

                                      {

                                                SplendidError.SystemError(new StackTrace(true).GetFrame(0), ex);

                                                ctlDynamicButtons.ErrorText = ex.Message;

                                      }

                             }

                             BindGrid();

 

                             if ( !IsPostBack )

                             {

                                      ctlDynamicButtons.AppendButtons("Teams." + m_sMODULE, Guid.Empty, gID);

                             }

                   }

 

                   #region Web Form Designer generated code

                   override protected void OnInit(EventArgs e)

                   {

                             //

                             // CODEGEN: This call is required by the ASP.NET Web Form Designer.

                             //

                             InitializeComponent();

                             base.OnInit(e);

                   }

                  

                   ///

                   ///                Required method for Designer support - do not modify

                   ///                the contents of this method with the code editor.

                   ///

                   private void InitializeComponent()

                   {

                             this.Load += new System.EventHandler(this.Page_Load);

                             ctlDynamicButtons.Command += new CommandEventHandler(Page_Command);

                             m_sMODULE = "Users";

                             arrSelectFields = new UniqueStringCollection();

                             arrSelectFields.Add("DATE_ENTERED"   );

                             arrSelectFields.Add("USER_ID"        );

                             arrSelectFields.Add("USER_NAME"      );

                             arrSelectFields.Add("FULL_NAME"      );

                             arrSelectFields.Add("EMAIL1"         );

                             arrSelectFields.Add("PHONE_WORK"     );

                             arrSelectFields.Add("EXPLICIT_ASSIGN");

                             if ( IsPostBack )

                                      ctlDynamicButtons.AppendButtons("Teams." + m_sMODULE, Guid.Empty, Guid.Empty);

                   }

                   #endregion

          }

}

 


Additional Information

The SplendidCRM Application Platform is constantly being improved.  Please visit the SplendidCRM Software website to obtain the most recent version of the software:

http://www.splendidcrm.com

If you have any questions, please post them to the SplendidCRM Support forum:

http://www.splendidcrm.com/Forums/tabid/66/Default.aspx

 

Errors and Omissions

If you discover any errors or omissions in this document, please email support@splendidcrm.com.