/// <summary> /// decodes the serailized panel Dataitem PK and sets the panel to it /// </summary> /// <param name="panel">active panel</param> /// <param name="queryString">URL-encoded PK</param> void SetRoutedPKForPanel(_min.Models.Panel panel, System.Collections.Specialized.NameValueCollection queryString) { DataRow row = mm.WebDriver.PKColRowFormat(panel); for (int i = 0; i < queryString.Count; i++) { string decoded = Server.UrlDecode(queryString[i]); if (row.Table.Columns[i].DataType == typeof(int)) { row[i] = Int32.Parse(decoded); } else if (row.Table.Columns[i].DataType == typeof(MySql.Data.Types.MySqlDateTime)) { row[i] = new MySql.Data.Types.MySqlDateTime(decoded); } else if (row.Table.Columns[i].DataType == typeof(DateTime)) { row[i] = DateTime.Parse(decoded); } else { row[i] = decoded; } } panel.PK = row; }
public Panel(string tableName, int panelId, PanelTypes type, List<Panel> children, List<IField> fields, List<Control> controls, List<string> PKColNames, DataRow PK = null, Panel parent = null) { this.tableName = tableName; this.panelId = panelId; this.children = children; this.fields = fields; this.controls = controls; this.PKColNames = PKColNames; this.PK = PK; this.parent = parent; this.type = type; if (this.controls == null) this.controls = new List<Control>(); if (this.fields == null) this.fields = new List<IField>(); if (this.PKColNames == null) this.PKColNames = new List<string>(); if (this.children == null) this.children = new List<Panel>(); foreach (Panel child in this.children) { child.parent = this; } foreach (IField f in this.fields) { f.Panel = this; } foreach (Control c in this.controls) { c.panel = this; } }
protected void Page_Init(object sender, EventArgs e) { ValidationResult.Items.Clear(); mm = (MinMaster)Master; string projectName = Page.RouteData.Values["projectName"] as string; int panelId = Int32.Parse(Page.RouteData.Values["panelId"] as string); actPanel = mm.SysDriver.Panels[panelId]; DataColumnCollection cols = mm.Stats.ColumnTypes[actPanel.tableName]; PanelName.Text = actPanel.panelName; _min.Models.Control control = actPanel.controls.Where(x => x is NavTableControl || x is TreeControl).First(); FKs = mm.Stats.FKs[actPanel.tableName]; List<string> colNames = (from DataColumn col in cols select col.ColumnName).ToList<string>(); // a M2NControl to select the columns of the table displayed in the GridView - for a tree we take only the first item DisplayCols.SetOptions(colNames); DisplayCols.SetIncludedOptions(control.displayColumns); // what actions can be triggered from the navigation control List<string> possibleAcitons = new List<string>(new string[] { UserAction.Insert.ToString(), UserAction.View.ToString(), UserAction.Delete.ToString() }); List<UserAction> originalActions = new List<UserAction>(); if (control is NavTableControl) { foreach(UserAction ua in ((NavTableControl)control).actions) originalActions.Add(ua); } else{ foreach (UserAction ua in ((TreeControl)control).actions) { originalActions.Add(ua); } } // if the panel contains a NavTable or TreeControl, it is the only control of a complex type and other controls therefore must be // simple buttons. foreach(_min.Models.Control simpleControl in actPanel.controls){ if(simpleControl == control) continue; originalActions.Add(simpleControl.action); } List<string> originalActionStrings = new List<string>(); foreach (UserAction a in originalActions) originalActionStrings.Add(a.ToString()); actionsControl.SetOptions(possibleAcitons); actionsControl.SetIncludedOptions(originalActionStrings); hierarchy = mm.Stats.SelfRefFKs().Find(x => x.myTable == actPanel.tableName); string[] CTypeOptions = hierarchy == null ? new string[] {"Navigation Table"} : new string[] {"Navigation Table", "Navigation Tree"}; // a radio button list - contains navtable and maybe treeview option NavControlType.DataSource = CTypeOptions; NavControlType.DataBind(); // let the default be the current if (control is TreeControl) NavControlType.SelectedIndex = 1; else NavControlType.SelectedIndex = 0; BackButton.PostBackUrl = BackButton.GetRouteUrl("ArchitectShowRoute", new { projectName = projectName }); }
/// <summary> /// initialization - add a Panel to the select box /// </summary> /// <param name="panel"></param> /// <param name="level"></param> private void AddPanelToList(MPanel panel, int level = 0) { DataRow r = panelsTable.NewRow(); r["Id"] = panel.panelId; r["Name"] = panel.panelName; panelsTable.Rows.Add(r); foreach (MPanel chp in panel.children) { AddPanelToList(chp, level + 1); } }
private bool ServerValidate(MPanel panel) { bool valid = true; foreach (_min.Interfaces.IField f in panel.fields) { f.Validate(); if (f.ErrorMessage != null) { valid = false; _min.Common.ValidationError.Display(f.ErrorMessage, Page); } } return(valid); }
/// <summary> /// stores the orinal hierarchy in a dataset that will be saved to viewstatee so that this doesn`t need to be called upon every postback. /// </summary> /// <param name="hierarchy">The data property of the original menu</param> /// <param name="basePanel">the root panel of the architecture</param> public void SetInitialState(DataTable hierarchy, MPanel basePanel) { hierarchyDataset = new DataSet(); menuHierarchy = new HierarchyNavTable(); panelsTable = new DataTable(); panelsTable.Columns.Add("Id", typeof(int)); panelsTable.Columns.Add("Name", typeof(string)); menuHierarchy.TableName = "menuHierarchy"; menuHierarchy.Merge(hierarchy); hierarchyDataset.Tables.Add(menuHierarchy); hierarchyDataset.Relations.Add(new DataRelation("Hierarchy", menuHierarchy.Columns["Id"], menuHierarchy.Columns["ParentId"], true)); AddPanelToList(basePanel); panelsTable.TableName = "panelsTable"; hierarchyDataset.Tables.Add(panelsTable); ViewState["hierarchyDS"] = hierarchyDataset; }
/// <summary> /// passes all the data collected to the Architect object, invoking its main method - Propose, which will generate the proposal /// and save it to the system database /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void InitProposalWizard_FinishButtonClick(object sender, WizardNavigationEventArgs e) { List <string> excludedTables = (List <string>)Session["excludedTables"]; Dictionary <string, string> displayColumnPreferences = (Dictionary <string, string>)Session["displayColumnPreferences"]; List <M2NMapping> finMappingsList = (List <M2NMapping>)Session["finMappingList"]; mm.Architect.mappings = finMappingsList; mm.Architect.excludedTables = excludedTables; mm.Stats.SetDisplayPreferences(displayColumnPreferences); mm.Architect.hierarchies = (List <string>)Session["goodHierarchies"]; // the main point _min.Models.Panel proposal = mm.Architect.propose(); // saved within proposing string projectName = Page.RouteData.Values["projectName"] as string; Response.RedirectToRoute("ArchitectShowRoute", new { projectName = CE.project.Name }); }
/// <summary> /// Deletes the row determined by the panel`s PK from the panl`s table. /// Also clears the mapping (this may not be neccessary if the constraint CASCADEs, but it is probably the desired behaviour in either case). /// </summary> /// <param name="panel"></param> public void DeleteFromPanel(Panel panel) { driver.BeginTransaction(); foreach (IField f in panel.fields) { if (f is M2NMappingField) { M2NMapping mapping = ((M2NMappingField)f).Mapping; UnmapM2NMappingKey(mapping, (int)(panel.PK[mapping.mapMyColumn])); } } int affected = driver.query("DELETE FROM", dbe.Table(panel.tableName), " WHERE", dbe.Condition(panel.PK)); if (affected > 1) { driver.RollbackTransaction(); throw new Exception("Panel PK not unique, trying to delete more rows at a time!"); } driver.CommitTransaction(); }
/// <summary> /// each custom field will get a cell in the main table containing a WebControls.Panel, into which it can display its customization form. /// Each customizable field is associated with a factory of corresponding type, which will load its properties and fill the fields of the customization form. /// The factory is also resposible for displaying and validating the form. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Init(object sender, EventArgs e) { mm = (MinMaster)Master; interPanel = (MPanel)Session["interPanel"]; // the custom fields have the basic settings alreadyu saved in the session - now only the custom parts will be configured. customs = (Dictionary <DataColumn, Dictionary <string, object> >)Session["customs"]; backButton.PostBackUrl = backButton.GetRouteUrl("ArchitectEditEditableRoute", new { projectName = mm.ProjectName, panelId = interPanel.panelId }); Table customSettingsTbl = new Table(); foreach (DataColumn customCol in customs.Keys) { TableRow captionRow = new TableRow(); TableCell captionCell = new TableCell(); captionCell.Text = customCol.ColumnName; captionRow.Cells.Add(captionCell); customSettingsTbl.Rows.Add(captionRow); TableRow settingsRow = new TableRow(); TableCell settingsCell = new TableCell(); WPanel container = new WPanel(); var factory = (ICustomizableColumnFieldFactory)customs[customCol]["factory"]; if (!Page.IsPostBack) { MPanel oldPanel = mm.SysDriver.Panels[interPanel.panelId]; IColumnField oldVersion = (IColumnField)(from f in oldPanel.fields where f.GetType() == factory.ProductionType && ((IColumnField)f).ColumnName == customCol.ColumnName select f).FirstOrDefault <IField>(); if (oldVersion != null) { factory.LoadProduct((IColumnField)oldVersion); } } factory.ShowForm(container); settingsCell.Controls.Add(container); settingsRow.Controls.Add(settingsCell); customSettingsTbl.Rows.Add(settingsRow); } MainPanel.Controls.Add(customSettingsTbl); }
protected void Page_Init(object sender, EventArgs e) { mm = (MinMaster)Master; //if (!Page.IsPostBack) //{ interPanel = (MPanel)Session["interPanel"]; customs = (Dictionary<DataColumn, Dictionary<string, object>>)Session["customs"]; backButton.PostBackUrl = backButton.GetRouteUrl("ArchitectEditEditableRoute", new { projectName = mm.ProjectName, panelId = interPanel.panelId }); //} Table customSettingsTbl = new Table(); foreach (DataColumn customCol in customs.Keys) { TableRow captionRow = new TableRow(); TableCell captionCell = new TableCell(); captionCell.Text = customCol.ColumnName; captionRow.Cells.Add(captionCell); customSettingsTbl.Rows.Add(captionRow); TableRow settingsRow = new TableRow(); TableCell settingsCell = new TableCell(); WPanel container = new WPanel(); var factory = (ICustomizableColumnFieldFactory)customs[customCol]["factory"]; if(!Page.IsPostBack){ MPanel oldPanel = mm.SysDriver.Panels[interPanel.panelId]; IColumnField oldVersion = (IColumnField)(from f in oldPanel.fields where f.GetType() == factory.ProductionType && ((IColumnField)f).ColumnName == customCol.ColumnName select f).FirstOrDefault<IField>(); if (oldVersion != null) factory.LoadProduct((IColumnField)oldVersion); } factory.ShowForm(container); settingsCell.Controls.Add(container); settingsRow.Controls.Add(settingsCell); customSettingsTbl.Rows.Add(settingsRow); } MainPanel.Controls.Add(customSettingsTbl); }
public void SetParentPanel(Panel parentPanel) { if (parent == null) parent = parentPanel; else throw new Exception("Panel parent already initialized"); }
public void AddChild(Panel p) { if (this.children.Any(p2 => p2.panelId == p.panelId)) throw new Exception("Panel already contains a child with this id."); this.children.Add(p); p.parent = this; }
private void CheckAgainstOriginalDataRow(Panel panel) { var columns = panel.fields.Where(x => x is IColumnField).Select(x => ((IColumnField)x).ColumnName).ToList<string>(); DataRow actualRow = driver.fetch("SELECT ", dbe.Cols(columns), " FROM ", dbe.Table(panel.tableName), "WHERE", dbe.Condition(panel.PK)); if (actualRow == null) throw new WebDriverDataModificationException( "The record could not be found. It may have been removed in the meantime."); //if(!DataRowComparer.Equals(actualRow, panel.OriginalData)) foreach(DataColumn col in actualRow.Table.Columns){ if((actualRow[col.ColumnName]).ToString() != (panel.OriginalData[col.ColumnName]).ToString()) // did not match equal rows otherways throw new WebDriverDataModificationException( "The record has been modified since loaded." + " Please save your data elsewhere and check for the new values."); } }
/// <summary> /// The structure of the panl`s PK property (a DataRow), no data included /// </summary> /// <param name="panel"></param> /// <returns></returns> public DataRow PKColRowFormat(Panel panel) { return driver.fetchSchema("SELECT ", dbe.Cols(panel.PKColNames), " FROM ", dbe.Table(panel.tableName)).NewRow(); }
public void FillPanelFKOptions(Panel panel) { foreach (IField field in panel.fields) { if (field is FKField) { // FK options FKField fkf = (FKField)field; fkf.FKOptions = FetchFKOptions(fkf.FK); } else if (field is M2NMappingField) { M2NMappingField m2nf = (M2NMappingField)field; m2nf.FKOptions = FetchFKOptions((FK)m2nf.Mapping); } } //foreach (Panel p in panel.children) //FillPanelFks(p); }
protected void SaveButton_Click(object sender, EventArgs e) { mm.SysDriver.FullProjectLoad(); int index = TablesGrid.SelectedIndex; string tableName = summary.Rows[index]["TableName"] as string; if ((bool)summary.Rows[index]["HasPanels"]) // then remove is the only option that could have been voted for { IEnumerable <MPanel> toRemove = from MPanel p in mm.SysDriver.Panels.Values where p.tableName == tableName select p; foreach (MPanel p in toRemove) { mm.SysDriver.RemovePanel(p); } summary.Rows[index]["HasPanels"] = false; } else { // otherwise add new editation a navigation panel for this table mm.Architect.mappings = mm.Stats.Mappings[tableName]; mm.Architect.hierarchies = new List <string>(); // to speed it up, hierarchy nvigation can be set in panel customization MPanel editPanel = mm.Architect.ProposeForTable(tableName); MPanel summaryPanel = mm.Architect.proposeSummaryPanel(tableName); summaryPanel.SetParentPanel(mm.SysDriver.MainPanel); // add to db editPanel.SetParentPanel(mm.SysDriver.MainPanel); foreach (_min.Models.Control c in editPanel.controls) { c.targetPanel = summaryPanel; } foreach (_min.Models.Control c in summaryPanel.controls) { c.targetPanel = editPanel; } summaryPanel.panelName = "Summary of " + tableName; editPanel.panelName = "Editation of " + tableName; mm.SysDriver.BeginTransaction(); mm.SysDriver.AddPanels(new List <_min.Models.Panel> { summaryPanel, editPanel }); mm.SysDriver.CommitTransaction(); foreach (_min.Models.Control c in summaryPanel.controls) // simlified for now { c.targetPanel = editPanel; } foreach (_min.Models.Control c in editPanel.controls) { c.targetPanel = summaryPanel; } summary.Rows[index]["HasPanels"] = true; } // rebuild the grid TablesGrid.DataSource = summary; TablesGrid.DataBind(); ResetActionClickablility(); TablesGrid.SelectedRow.BackColor = System.Drawing.Color.White; TablesGrid.SelectedRowStyle.BackColor = System.Drawing.Color.White; TablesGrid.SelectedIndex = -1; SaveButton.Enabled = false; mm.SysDriver.IncreaseVersionNumber(); Session["summary"] = summary; }
protected void Page_Init(object sender, EventArgs e) { mm = (MinMaster)Master; factories = (List <IColumnFieldFactory>)Application["ColumnFieldFactories"]; int panelId = Int32.Parse(Page.RouteData.Values["panelId"] as string); actPanel = mm.SysDriver.Panels[panelId]; DataColumnCollection cols = mm.Stats.ColumnTypes[actPanel.tableName]; // the field types - default and special subsets allowed for special data types - i.e. a foereign key cannot be edited via nothing but // a FKFiels string[] fieldTypes = new string[] { FieldTypes.ShortText.ToString(), FieldTypes.Bool.ToString(), FieldTypes.Date.ToString(), FieldTypes.DateTime.ToString(), FieldTypes.Text.ToString() }; string[] EnumType = new string[] { FieldTypes.Enum.ToString() }; string[] FKtype = new string[] { FieldTypes.FK.ToString() }; string[] mappingType = new string[] { FieldTypes.M2NMapping.ToString() }; string[] validationRules = Enum.GetNames(typeof(ValidationRules)); //possible bugpoing (see repo) // a FKField can be only required - let referential integrity take care of the rest string[] requiredRule = new string[] { Enum.GetName(typeof(ValidationRules), ValidationRules.Required) }; FKs = mm.Stats.FKs[actPanel.tableName]; mappings = new List <M2NMapping>(); mappings = mm.Stats.Mappings[actPanel.tableName]; panelName.Text = actPanel.panelName; // create a datarow for each column, specifiing... foreach (DataColumn col in cols) // std. fields (incl. FKs) { IColumnField cf = (IColumnField)actPanel.fields.Find(x => x is IColumnField && ((IColumnField)x).ColumnName == col.ColumnName); TableRow r = new TableRow(); r.ID = col.ColumnName; //...the name,... TableCell nameCell = new TableCell(); Label nameLabel = new Label(); nameLabel.Text = col.ColumnName; nameCell.Controls.Add(nameLabel); r.Cells.Add(nameCell); //...whether the column will be accessible to editation at all,... TableCell presentCell = new TableCell(); CheckBox present = new CheckBox(); present.Checked = cf != null; presentCell.Controls.Add(present); r.Cells.Add(presentCell); FK fk = FKs.Find(x => x.myColumn == col.ColumnName); if (cf != null && cf is FKField) { fk = ((FKField)cf).FK; } //...the FieldType,... TableCell typeCell = new TableCell(); DropDownList dl = new DropDownList(); Dictionary <int, string> typeOptions = new Dictionary <int, string>(); int current = -1; for (int i = 0; i < factories.Count; i++) { if (factories[i].CanHandle(col)) { typeOptions.Add(i, factories[i].UIName); } if (cf != null && cf.GetType() == (factories[i].ProductionType)) { current = typeOptions.Count - 1; } } dl.DataSource = typeOptions; dl.DataValueField = "Key"; dl.DataTextField = "Value"; dl.DataBind(); dl.SelectedIndex = current; typeCell.Controls.Add(dl); r.Cells.Add(typeCell); //...what column of the referred table to display in the dropdown TableCell FKDisplayCell = new TableCell(); // set default value if the field was originally present in the editation form if (fk != null) { DropDownList fkddl = new DropDownList(); fkddl.DataSource = mm.Stats.ColumnsToDisplay[fk.refTable]; fkddl.DataBind(); if (cf != null) { fkddl.SelectedIndex = fkddl.Items.IndexOf(fkddl.Items.FindByValue(((FKField)cf).FK.displayColumn)); } FKDisplayCell.Controls.Add(fkddl); } r.Cells.Add(FKDisplayCell); //PBPR //...the validation rules... TableCell validCell = new TableCell(); CheckBox requiredCb = new CheckBox(); Label requiredlabel = new Label(); requiredlabel.Text = "required "; CheckBox uniCheck = new CheckBox(); Label uniLabel = new Label(); uniLabel.Text = "unique"; if (cf != null) { requiredCb.Checked = cf.Required; uniCheck.Checked = cf.Unique; } if (!(cf is CheckBoxField)) { validCell.Controls.Add(requiredlabel); validCell.Controls.Add(requiredCb); validCell.Controls.Add(uniLabel); validCell.Controls.Add(uniCheck); } r.Cells.Add(validCell); //...and the caption TableCell captionCell = new TableCell(); TextBox caption = new TextBox(); captionCell.Controls.Add(caption); r.Cells.Add(captionCell); if (cf != null) { caption.Text = cf.Caption; } // index 6 tbl.Rows.Add(r); } // mappings will get a similiar table, but some collumns (like validation) will just be left empty foreach (M2NMapping mapping in mappings) { M2NMappingField f = actPanel.fields.Find( x => x is M2NMappingField && ((M2NMappingField)x).Mapping.myColumn == mapping.myColumn) as M2NMappingField; TableRow r = new TableRow(); TableCell nameCell = new TableCell(); Label nameLabel = new Label(); nameLabel.Text = mapping.myTable + " to " + mapping.refTable + " via " + mapping.mapTable; nameCell.Controls.Add(nameLabel); r.Cells.Add(nameCell); TableCell presentCell = new TableCell(); CheckBox present = new CheckBox(); present.Checked = f != null; presentCell.Controls.Add(present); r.Cells.Add(presentCell); TableCell typeCell = new TableCell(); DropDownList dl = new DropDownList(); dl.DataSource = mappingType; dl.DataBind(); typeCell.Controls.Add(dl); r.Cells.Add(typeCell); TableCell displayCell = new TableCell(); DropDownList displayDrop = new DropDownList(); displayDrop.DataSource = mm.Stats.ColumnsToDisplay[mapping.refTable]; displayDrop.DataBind(); if (f != null) { displayDrop.SelectedIndex = displayDrop.Items.IndexOf(displayDrop.Items.FindByValue(f.Mapping.displayColumn)); } displayCell.Controls.Add(displayDrop); r.Cells.Add(displayCell); TableCell validCell = new TableCell(); // leave it empty r.Cells.Add(validCell); TableCell captionCell = new TableCell(); TextBox caption = new TextBox(); captionCell.Controls.Add(caption); r.Cells.Add(captionCell); if (f != null) { caption.Text = f.Caption; } mappingsTbl.Rows.Add(r); } // what can be done with the panel string[] actionTypes = new string[] { UserAction.Insert.ToString(), UserAction.Update.ToString(), UserAction.Delete.ToString() }; // controls List <string> activeActions = (from _min.Models.Control control in actPanel.controls select Enum.GetName(typeof(UserAction), control.action)).ToList <string>(); actions.SetOptions(new List <string>(actionTypes)); actions.SetIncludedOptions(activeActions); backButton.PostBackUrl = backButton.GetRouteUrl("ArchitectShowRoute", new { projectName = mm.ProjectName }); }
protected void SaveButton_Click(object sender, EventArgs e) { // extract the data for fields from the table List <IField> fields = new List <IField>(); int i = 1; Dictionary <DataColumn, Dictionary <string, object> > customs = new Dictionary <DataColumn, Dictionary <string, object> >(); foreach (DataColumn col in mm.Stats.ColumnTypes[actPanel.tableName]) { // standard fields TableRow r = tbl.Rows[i++]; if (!((CheckBox)r.Cells[1].Controls[0]).Checked) { continue; } // label, present, type, valid, caption IColumnFieldFactory factory = factories[Int32.Parse(((DropDownList)r.Cells[2].Controls[0]).SelectedValue)]; // cell 3 is there for FK display column dropList bool required = false; bool unique = false; if (r.Cells[4].Controls.Count == 4) { CheckBox reqChb = (CheckBox)r.Cells[4].Controls[1]; CheckBox uniChb = (CheckBox)r.Cells[4].Controls[3]; required = reqChb.Checked; unique = uniChb.Checked; } string caption = ((TextBox)r.Cells[5].Controls[0]).Text; if (caption == "") { caption = null; } if (factory is ICustomizableColumnFieldFactory) { customs[col] = new Dictionary <string, object>(); customs[col]["factory"] = factory.Clone(); // so that each field gets its factory even if there more custom fields of the same type customs[col]["required"] = required; customs[col]["unique"] = unique; customs[col]["caption"] = caption; continue; } IField newField; //PBPR // react to the changes to the displaycolumn for the FK if (col.ExtendedProperties.Contains("FK")) { FK colFK = (FK)(col.ExtendedProperties["FK"]); colFK.displayColumn = ((DropDownList)(r.Cells[3].Controls[0])).SelectedValue; col.ExtendedProperties["FK"] = colFK; } newField = factory.Create(col); newField.Caption = caption; newField.Required = required; if (newField is IColumnField) { ((IColumnField)newField).Unique = unique; } fields.Add(newField); } i = 1; foreach (M2NMapping mapping in mappings) { // mappings TableRow r = mappingsTbl.Rows[i++]; // label, present, type (mappingType), valid (req?), caption if (!((CheckBox)r.Cells[1].Controls[0]).Checked) { continue; } // must be mappingType... List <ValidationRules> rules = new List <ValidationRules>(); // no validation for a mapping mapping.displayColumn = ((DropDownList)(r.Cells[3].Controls[0])).SelectedValue; string caption = ((TextBox)r.Cells[5].Controls[0]).Text; M2NMappingField m2nf = new M2NMappingField(mapping, caption); fields.Add(m2nf); } // crate a control for each checked action List <_min.Models.Control> controls = new List <_min.Models.Control>(); // controls bool valid = true; List <string> errorMsgs = new List <string>(); if (actions.RetrieveStringData().Count == 0) { valid = false; errorMsgs.Add("Choose at least one action for the panel, please."); } foreach (string actionString in actions.RetrieveStringData()) { _min.Models.Control c = new _min.Models.Control(0, actionString, (UserAction)Enum.Parse(typeof(UserAction), actionString)); c.targetPanel = actPanel.controls[0].targetPanel; c.targetPanelId = actPanel.controls[0].targetPanelId; // a miserable way to find out the target panel...really controls.Add(c); } MPanel resPanel = new MPanel(actPanel.tableName, actPanel.panelId, PanelTypes.Editable, new List <MPanel>(), fields, controls, actPanel.PKColNames, null, actPanel.parent); resPanel.panelName = panelName.Text; valid = valid && mm.Architect.checkPanelProposal(resPanel, out errorMsgs, customs); // validate the Panel using Architect`s validator - don`t edit PKs, unique columns must have the constraint, must contain all collumns except Nullable // and AI and more rules validationResult.Items.Clear(); if (valid) { if (customs.Count == 0) { validationResult.Items.Add(new ListItem("Valid")); actPanel = resPanel; mm.SysDriver.BeginTransaction(); mm.SysDriver.UpdatePanel(actPanel); Session.Clear(); mm.SysDriver.IncreaseVersionNumber(); mm.SysDriver.CommitTransaction(); validationResult.Items.Add(new ListItem("Saved")); Response.Redirect(Page.Request.RawUrl); } else { Session["interPanel"] = resPanel; Session["customs"] = customs; Response.RedirectToRoute("ArchitectEditEditableCustomRoute", new { projectName = CE.project.Name, panelId = actPanel.panelId }); // for the sake of unity (and SysDriver) } } else { foreach (string s in errorMsgs) { validationResult.Items.Add(new ListItem(s)); } } }
protected void Page_Init(object sender, EventArgs e) { mm = (MinMaster)Master; factories = (List<IColumnFieldFactory>)Application["ColumnFieldFactories"]; int panelId = Int32.Parse(Page.RouteData.Values["panelId"] as string); actPanel = mm.SysDriver.Panels[panelId]; DataColumnCollection cols = mm.Stats.ColumnTypes[actPanel.tableName]; // the field types - default and special subsets allowed for special data types - i.e. a foereign key cannot be edited via nothing but // a FKFiels string[] fieldTypes = new string[] { FieldTypes.ShortText.ToString(), FieldTypes.Bool.ToString(), FieldTypes.Date.ToString(), FieldTypes.DateTime.ToString(), FieldTypes.Text.ToString() }; string[] EnumType = new string[] { FieldTypes.Enum.ToString() }; string[] FKtype = new string[] { FieldTypes.FK.ToString() }; string[] mappingType = new string[] { FieldTypes.M2NMapping.ToString() }; string[] validationRules = Enum.GetNames(typeof(ValidationRules)); //possible bugpoing (see repo) // a FKField can be only required - let referential integrity take care of the rest string[] requiredRule = new string[] { Enum.GetName(typeof(ValidationRules), ValidationRules.Required) }; FKs = mm.Stats.FKs[actPanel.tableName]; mappings = new List<M2NMapping>(); mappings = mm.Stats.Mappings[actPanel.tableName]; panelName.Text = actPanel.panelName; // create a datarow for each column, specifiing... foreach (DataColumn col in cols) { // std. fields (incl. FKs) IColumnField cf = (IColumnField)actPanel.fields.Find(x => x is IColumnField && ((IColumnField)x).ColumnName == col.ColumnName); TableRow r = new TableRow(); r.ID = col.ColumnName; //...the name,... TableCell nameCell = new TableCell(); Label nameLabel = new Label(); nameLabel.Text = col.ColumnName; nameCell.Controls.Add(nameLabel); r.Cells.Add(nameCell); //...whether the column will be accessible to editation at all,... TableCell presentCell = new TableCell(); CheckBox present = new CheckBox(); present.Checked = cf != null; presentCell.Controls.Add(present); r.Cells.Add(presentCell); FK fk = FKs.Find(x => x.myColumn == col.ColumnName); if(cf != null && cf is FKField) fk = ((FKField)cf).FK; //...the FieldType,... TableCell typeCell = new TableCell(); DropDownList dl = new DropDownList(); Dictionary<int, string> typeOptions = new Dictionary<int, string>(); int current = -1; for (int i = 0; i < factories.Count; i++) { if (factories[i].CanHandle(col)) typeOptions.Add(i, factories[i].UIName); if(cf != null && cf.GetType() == (factories[i].ProductionType)){ current = typeOptions.Count - 1; } } dl.DataSource = typeOptions; dl.DataValueField = "Key"; dl.DataTextField = "Value"; dl.DataBind(); dl.SelectedIndex = current; typeCell.Controls.Add(dl); r.Cells.Add(typeCell); //...what column of the referred table to display in the dropdown TableCell FKDisplayCell = new TableCell(); // set default value if the field was originally present in the editation form if (fk != null) { DropDownList fkddl = new DropDownList(); fkddl.DataSource = mm.Stats.ColumnsToDisplay[fk.refTable]; fkddl.DataBind(); if(cf != null) fkddl.SelectedIndex = fkddl.Items.IndexOf(fkddl.Items.FindByValue(((FKField)cf).FK.displayColumn)); FKDisplayCell.Controls.Add(fkddl); } r.Cells.Add(FKDisplayCell); //PBPR //...the validation rules... TableCell validCell = new TableCell(); CheckBox requiredCb = new CheckBox(); Label requiredlabel = new Label(); requiredlabel.Text = "required "; CheckBox uniCheck = new CheckBox(); Label uniLabel = new Label(); uniLabel.Text = "unique"; if (cf != null) { requiredCb.Checked = cf.Required; uniCheck.Checked = cf.Unique; } if (!(cf is CheckBoxField)) { validCell.Controls.Add(requiredlabel); validCell.Controls.Add(requiredCb); validCell.Controls.Add(uniLabel); validCell.Controls.Add(uniCheck); } r.Cells.Add(validCell); //...and the caption TableCell captionCell = new TableCell(); TextBox caption = new TextBox(); captionCell.Controls.Add(caption); r.Cells.Add(captionCell); if (cf != null) { caption.Text = cf.Caption; } // index 6 tbl.Rows.Add(r); } // mappings will get a similiar table, but some collumns (like validation) will just be left empty foreach (M2NMapping mapping in mappings) { M2NMappingField f = actPanel.fields.Find( x => x is M2NMappingField && ((M2NMappingField)x).Mapping.myColumn == mapping.myColumn) as M2NMappingField; TableRow r = new TableRow(); TableCell nameCell = new TableCell(); Label nameLabel = new Label(); nameLabel.Text = mapping.myTable + " to " + mapping.refTable + " via " + mapping.mapTable; nameCell.Controls.Add(nameLabel); r.Cells.Add(nameCell); TableCell presentCell = new TableCell(); CheckBox present = new CheckBox(); present.Checked = f != null; presentCell.Controls.Add(present); r.Cells.Add(presentCell); TableCell typeCell = new TableCell(); DropDownList dl = new DropDownList(); dl.DataSource = mappingType; dl.DataBind(); typeCell.Controls.Add(dl); r.Cells.Add(typeCell); TableCell displayCell = new TableCell(); DropDownList displayDrop = new DropDownList(); displayDrop.DataSource = mm.Stats.ColumnsToDisplay[mapping.refTable]; displayDrop.DataBind(); if (f != null) { displayDrop.SelectedIndex = displayDrop.Items.IndexOf(displayDrop.Items.FindByValue(f.Mapping.displayColumn)); } displayCell.Controls.Add(displayDrop); r.Cells.Add(displayCell); TableCell validCell = new TableCell(); // leave it empty r.Cells.Add(validCell); TableCell captionCell = new TableCell(); TextBox caption = new TextBox(); captionCell.Controls.Add(caption); r.Cells.Add(captionCell); if (f != null) { caption.Text = f.Caption; } mappingsTbl.Rows.Add(r); } // what can be done with the panel string[] actionTypes = new string[] { UserAction.Insert.ToString(), UserAction.Update.ToString(), UserAction.Delete.ToString() }; // controls List<string> activeActions = (from _min.Models.Control control in actPanel.controls select Enum.GetName(typeof(UserAction), control.action)).ToList<string>(); actions.SetOptions(new List<string>(actionTypes)); actions.SetIncludedOptions(activeActions); backButton.PostBackUrl = backButton.GetRouteUrl("ArchitectShowRoute", new { projectName = mm.ProjectName }); }
protected void SaveButton_Click(object sender, EventArgs e) { // extract the data for fields from the table List<IField> fields = new List<IField>(); int i = 1; Dictionary<DataColumn, Dictionary<string, object>> customs = new Dictionary<DataColumn, Dictionary<string, object>>(); foreach (DataColumn col in mm.Stats.ColumnTypes[actPanel.tableName]) { // standard fields TableRow r = tbl.Rows[i++]; if (!((CheckBox)r.Cells[1].Controls[0]).Checked) continue; // label, present, type, valid, caption IColumnFieldFactory factory = factories[Int32.Parse(((DropDownList)r.Cells[2].Controls[0]).SelectedValue)]; // cell 3 is there for FK display column dropList bool required = false; bool unique = false; if(r.Cells[4].Controls.Count == 4){ CheckBox reqChb = (CheckBox)r.Cells[4].Controls[1]; CheckBox uniChb = (CheckBox)r.Cells[4].Controls[3]; required = reqChb.Checked; unique = uniChb.Checked; } string caption = ((TextBox)r.Cells[5].Controls[0]).Text; if (caption == "") caption = null; if (factory is ICustomizableColumnFieldFactory) { customs[col] = new Dictionary<string, object>(); customs[col]["factory"] = factory.Clone(); // so that each field gets its factory even if there more custom fields of the same type customs[col]["required"] = required; customs[col]["unique"] = unique; customs[col]["caption"] = caption; continue; } IField newField; //PBPR // react to the changes to the displaycolumn for the FK if (col.ExtendedProperties.Contains("FK")) { FK colFK = (FK)(col.ExtendedProperties["FK"]); colFK.displayColumn = ((DropDownList)(r.Cells[3].Controls[0])).SelectedValue; col.ExtendedProperties["FK"] = colFK; } newField = factory.Create(col); newField.Caption = caption; newField.Required = required; if (newField is IColumnField) { ((IColumnField)newField).Unique = unique; } fields.Add(newField); } i = 1; foreach (M2NMapping mapping in mappings) { // mappings TableRow r = mappingsTbl.Rows[i++]; // label, present, type (mappingType), valid (req?), caption if (!((CheckBox)r.Cells[1].Controls[0]).Checked) continue; // must be mappingType... List<ValidationRules> rules = new List<ValidationRules>(); // no validation for a mapping mapping.displayColumn = ((DropDownList)(r.Cells[3].Controls[0])).SelectedValue; string caption = ((TextBox)r.Cells[5].Controls[0]).Text; M2NMappingField m2nf = new M2NMappingField(mapping, caption); fields.Add(m2nf); } // crate a control for each checked action List<_min.Models.Control> controls = new List<_min.Models.Control>(); // controls bool valid = true; List<string> errorMsgs = new List<string>(); if (actions.RetrieveStringData().Count == 0) { valid = false; errorMsgs.Add("Choose at least one action for the panel, please."); } foreach (string actionString in actions.RetrieveStringData()) { _min.Models.Control c = new _min.Models.Control(0, actionString, (UserAction)Enum.Parse(typeof(UserAction), actionString)); c.targetPanel = actPanel.controls[0].targetPanel; c.targetPanelId = actPanel.controls[0].targetPanelId; // a miserable way to find out the target panel...really controls.Add(c); } MPanel resPanel = new MPanel(actPanel.tableName, actPanel.panelId, PanelTypes.Editable, new List<MPanel>(), fields, controls, actPanel.PKColNames, null, actPanel.parent); resPanel.panelName = panelName.Text; valid = valid && mm.Architect.checkPanelProposal(resPanel, out errorMsgs, customs); // validate the Panel using Architect`s validator - don`t edit PKs, unique columns must have the constraint, must contain all collumns except Nullable // and AI and more rules validationResult.Items.Clear(); if (valid) { if (customs.Count == 0) { validationResult.Items.Add(new ListItem("Valid")); actPanel = resPanel; mm.SysDriver.BeginTransaction(); mm.SysDriver.UpdatePanel(actPanel); Session.Clear(); mm.SysDriver.IncreaseVersionNumber(); mm.SysDriver.CommitTransaction(); validationResult.Items.Add(new ListItem("Saved")); Response.Redirect(Page.Request.RawUrl); } else { Session["interPanel"] = resPanel; Session["customs"] = customs; Response.RedirectToRoute("ArchitectEditEditableCustomRoute", new {projectName = CE.project.Name, panelId = actPanel.panelId}); // for the sake of unity (and SysDriver) } } else { foreach (string s in errorMsgs) { validationResult.Items.Add(new ListItem(s)); } } }
protected void Page_Init(object sender, EventArgs e) { ValidationResult.Items.Clear(); mm = (MinMaster)Master; string projectName = Page.RouteData.Values["projectName"] as string; int panelId = Int32.Parse(Page.RouteData.Values["panelId"] as string); actPanel = mm.SysDriver.Panels[panelId]; DataColumnCollection cols = mm.Stats.ColumnTypes[actPanel.tableName]; PanelName.Text = actPanel.panelName; _min.Models.Control control = actPanel.controls.Where(x => x is NavTableControl || x is TreeControl).First(); FKs = mm.Stats.FKs[actPanel.tableName]; List <string> colNames = (from DataColumn col in cols select col.ColumnName).ToList <string>(); // a M2NControl to select the columns of the table displayed in the GridView - for a tree we take only the first item DisplayCols.SetOptions(colNames); DisplayCols.SetIncludedOptions(control.displayColumns); // what actions can be triggered from the navigation control List <string> possibleAcitons = new List <string>(new string[] { UserAction.Insert.ToString(), UserAction.View.ToString(), UserAction.Delete.ToString() }); List <UserAction> originalActions = new List <UserAction>(); if (control is NavTableControl) { foreach (UserAction ua in ((NavTableControl)control).actions) { originalActions.Add(ua); } } else { foreach (UserAction ua in ((TreeControl)control).actions) { originalActions.Add(ua); } } // if the panel contains a NavTable or TreeControl, it is the only control of a complex type and other controls therefore must be // simple buttons. foreach (_min.Models.Control simpleControl in actPanel.controls) { if (simpleControl == control) { continue; } originalActions.Add(simpleControl.action); } List <string> originalActionStrings = new List <string>(); foreach (UserAction a in originalActions) { originalActionStrings.Add(a.ToString()); } actionsControl.SetOptions(possibleAcitons); actionsControl.SetIncludedOptions(originalActionStrings); hierarchy = mm.Stats.SelfRefFKs().Find(x => x.myTable == actPanel.tableName); string[] CTypeOptions = hierarchy == null ? new string[] { "Navigation Table" } : new string[] { "Navigation Table", "Navigation Tree" }; // a radio button list - contains navtable and maybe treeview option NavControlType.DataSource = CTypeOptions; NavControlType.DataBind(); // let the default be the current if (control is TreeControl) { NavControlType.SelectedIndex = 1; } else { NavControlType.SelectedIndex = 0; } BackButton.PostBackUrl = BackButton.GetRouteUrl("ArchitectShowRoute", new { projectName = projectName }); }
/// <summary> /// Saves a new panel to the database (must have null ID, which will be changed to the new AI inserted in DB). /// </summary> /// <param name="panel"></param> /// <param name="recursive"></param> public void AddPanel(Panel panel, bool recursive = true) { AddPanelOnly(panel, recursive); SetControlPanelBindings(panel, recursive); AddPanelFieldsOnly(panel, recursive); AddPanelControlsOnly(panel, recursive); }
// all the panel`s controls will be bound to their target panel /// <summary> /// Sets targetPanelId property of the given panel controls to the targetPanel`s id so that this can be serialized and saved to database. /// </summary> /// <param name="panel"></param> /// <param name="recursive"></param> private void SetControlPanelBindings(Panel panel, bool recursive = true) { foreach (Control c in panel.controls) { if (c.targetPanelId != null) throw new Exception("Target panel id already set!"); if (c.targetPanel != null) { c.targetPanelId = c.targetPanel.panelId; } } if (recursive) foreach (Panel p in panel.children) SetControlPanelBindings(p); }
/// <summary> /// Removes the given panel from the database. /// </summary> /// <param name="panel"></param> public void RemovePanel(Panel panel) { driver.query("DELETE FROM ", dbe.Table("panels"), " WHERE ", dbe.Table("id_panel"), " = ", panel.panelId); }
public IPanel getPanel(int panelId, bool recursive = true, IPanel parent = null) { DataRow panelRow = fetch("SELECT * FROM panels " + " JOIN panel_types USING(id_panel) WHERE id_panel = ", panelId); List<Field> fields = PanelFields(panelId); List<string> PKColNames = new List<string>(((string)panelRow["pk_column_names"]).Split(',')); PropertyCollection viewProperties = new PropertyCollection(); PropertyCollection controlProperties = new PropertyCollection(); // !! attrs to handle global validation rules needed? DataTable propsTab = fetchAll("SELECT name, val, concerns FROM panels_meta WHERE id_panel = ", panelId); foreach(DataRow row in propsTab.Rows) switch(row["concerns"] as string){ case CC.ATTR_VIEW: viewProperties.Add(row["name"], row["val"]); break; case CC.ATTR_CONTROLS: controlProperties.Add(row["name"], row["val"]); break; default: throw new Exception("Cannot handle panel properties concerning " + row["concerns"] as string + " (yet). "); } //determine the controls List<Control> controls = new List<Control>(); // TODO (probably don`t) rewrite into enum over PanelTypes string pTypeStr = (string)panelRow["type_name"]; switch(pTypeStr){ case Constants.PANEL_EDITABLE: // standard edit window case Constants.PANEL_NAVTABLE: foreach(UserAction action in Enum.GetValues(typeof(UserAction))){ if((action == UserAction.View && pTypeStr == Constants.PANEL_EDITABLE) || (action == UserAction.Update && pTypeStr == Constants.PANEL_NAVTABLE ) ) continue; string actionName = action.ToString(); string controlCaption = (string)controlProperties[actionName]; //!! if(controlCaption != CC.CONTROL_DISABLED && (int)controlProperties[actionName + "ALR"] <= CE.user.rights){ // Authorization Level Required controls.Add(new Control(controlCaption, action)); } } break; case CC.PANEL_MONITOR: // just display, no controls break; case CC.PANEL_MENUDROP: // the contol is the whole panel, do not load data case CC.PANEL_MENUTABS: // will be a field type case CC.PANEL_NAVTREE: string localActionName = UserAction.View.ToString(); // duplicite information about controls - in controlProperties and as Control objects. For Proposal phase use only if((string)controlProperties[localActionName] != CC.CONTROL_DISABLED && // there is sth to show and user can see it (int)controlProperties[localActionName + "ALR"] <= (int)CE.user.rights){ DataTable controlTabStruct = new DataTable(); List<string> displayColumns = new List<string>( // table structure for summary (viewProperties[CC.PANEL_DISPLAY_COLUMN_ORDER] as string).Split(',')); // already in database - only first few columns string panelTypeName = (string)panelRow["type_name"]; if (panelTypeName == CC.PANEL_MENUTABS) { // will take data from children (captions as panel Names) controlTabStruct.Columns.Add("childPanelName"); controls.Add(new Control(controlTabStruct, "childPanelName", UserAction.View)); } else { // gotta be navTree or menuDrop => treeControl if (PKColNames.Count > 1) // must have single PKcol throw new Exception("Tree hierarchies must have single-column primay key"); controlTabStruct.Columns.Add(PKColNames[0]); controlTabStruct.Columns.Add(controlProperties[CC.CONTROL_HIERARCHY_SELF_FK_COL] as string); controlTabStruct.Columns.Add(displayColumns[0]); controls.Add(new TreeControl( controlTabStruct, PKColNames[0], controlProperties[CC.CONTROL_HIERARCHY_SELF_FK_COL] as string, displayColumns[0], UserAction.View)); } } break; } List<IField> fieldsAsInterface = new List<IField>(fields); List<IControl> controlsAsInterface = new List<IControl>(controls); Panel res = new Panel(panelRow["table_name"] as string, panelId, (int)panelRow["id_type"], panelRow["type_name"] as string, null, fieldsAsInterface, controlsAsInterface, PKColNames, null, viewProperties, controlProperties, parent); if(recursive) res.AddChildren(getPanelChildren(res, true)); return res; }
public void SetArchitecture(Panel mainPanel) { MainPanel = mainPanel; Panels = new Dictionary<int, Panel>(); FlattenPanel(MainPanel); }
/// <summary> /// inserts a new row into the table managed by the panel, with the vlaues stored in it`s fields, also inserts in mapping tables /// </summary> /// <param name="panel"></param> /// <returns></returns> public int InsertIntoPanel(Panel panel) { foreach (IField f in panel.fields) { if(f is IColumnField) { IColumnField cf = (IColumnField)f; if (panel.RetrievedManagedData[cf.ColumnName] != null && cf.Unique) { bool unique = driver.CheckUniqueness(panel.tableName, cf.ColumnName, panel.RetrievedManagedData[cf.ColumnName]); if (!unique) throw new ConstraintException("Field \"" + cf.Caption + "\" is restrained to be unique and \"" + cf.Data.ToString() + "\" is already present"); } } } int ID; try { driver.BeginTransaction(); driver.query("INSERT INTO ", dbe.Table(panel.tableName), dbe.InsVals(panel.RetrievedInsertData)); ID = driver.LastId(); // TODO safe? Does transaction ensure insert separation? driver.CommitTransaction(); } catch (MySql.Data.MySqlClient.MySqlException mye) { // Can occur, if there is a unique Key on multiple columns - such constraint cannot be set in panel management // (very rare indeed). The exception is attached a user-friendly comment and bubbles to the Show.cs, where // it will be displayed as a standard validation error (but probably with a notable delay). // will already be out of transaction - BaseDriver closes it immediately //if(IsInTransaction) // driver.RollbackTransaction(); throw new ConstraintException(FriendlyConstraintException(mye.Message, panel), null); } foreach (IField f in panel.fields) { if (f is M2NMappingField) { M2NMappingField m2nf = (M2NMappingField)f; MapM2NVals(m2nf.Mapping, ID, (List<int>)m2nf.Data); } } return ID; }
protected void SaveButton_Click(object sender, EventArgs e) { string panelName = PanelName.Text; List<string> displayCols = DisplayCols.RetrieveStringData(); List<UserAction> actions = new List<UserAction>(); foreach(string s in actionsControl.RetrieveStringData()){ actions.Add((UserAction)Enum.Parse(typeof(UserAction), s)); } ValidationResult.Items.Clear(); // validate the proposal if (panelName == ".") { ValidationResult.Items.Add("Give the pannel a name, please."); } else if (displayCols.Count == 0) { ValidationResult.Items.Add("Select at leas one column to display"); } else if (actions.Count == 0) { ValidationResult.Items.Add("Check at least one action users can perform in thie panel, please"); } else { ValidationResult.Items.Add("Valid"); // => create the panel and save it _min.Models.Control c; List<_min.Models.Control> controls = new List<_min.Models.Control>(); _min.Models.Control insertButton = null; // insert is a separate button if (actions.Contains(UserAction.Insert)) { insertButton = new _min.Models.Control(actPanel.panelId, "Insert", UserAction.Insert); actions.Remove(UserAction.Insert); } // it is a NavTable if (NavControlType.SelectedValue.EndsWith("Table")) { List<FK> neededFKs = (from FK fk in FKs where displayCols.Contains(fk.myColumn) select fk).ToList<FK>(); c = new NavTableControl(actPanel.panelId, new System.Data.DataTable(), mm.Stats.PKs[actPanel.tableName], neededFKs, actions); c.displayColumns = displayCols; } else { // NavTree actions.Remove(UserAction.Delete); // cannot use delete in NavTrees c = new TreeControl(actPanel.panelId, new HierarchyNavTable(), mm.Stats.PKs[actPanel.tableName][0], hierarchy.myColumn, displayCols[0], actions); } controls.Add(c); if (insertButton != null) controls.Add(insertButton); foreach (_min.Models.Control listedControl in controls) { listedControl.targetPanelId = actPanel.controls[0].targetPanelId; } MPanel resPanel = new MPanel(actPanel.tableName, actPanel.panelId, c is TreeControl ? PanelTypes.NavTree : PanelTypes.NavTable, new List<MPanel>(), new List<IField>(), controls, actPanel.PKColNames, null, actPanel.parent); resPanel.panelName = panelName; actPanel = resPanel; mm.SysDriver.BeginTransaction(); mm.SysDriver.UpdatePanel(actPanel); mm.SysDriver.CommitTransaction(); mm.SysDriver.IncreaseVersionNumber(); ValidationResult.Items.Add("Saved"); Response.Redirect(Page.Request.RawUrl); } }
/// <summary> /// updates the db row identified by the panel PK, using data from panel fields /// </summary> /// <param name="panel"></param> // TODO : row PK cannot change once created! public void UpdatePanel(Panel panel) { CheckAgainstOriginalDataRow(panel); foreach (IField f in panel.fields) { if (f is IColumnField) { IColumnField cf = (IColumnField)f; if (cf.Unique && panel.RetrievedManagedData[cf.ColumnName] != null) // TODO make sure all fields are set to null when should be { bool unique = driver.CheckUniqueness(panel.tableName, cf.ColumnName, panel.RetrievedManagedData[cf.ColumnName], panel.PK); if (!unique) throw new ConstraintException("Field \"" + cf.Data + "\" is restrained to be unique and \"" + cf.Data.ToString() + "\" is already present"); } } } foreach (DataColumn PKcol in panel.PK.Table.Columns) { // row PK midified if (panel.PK[PKcol.ColumnName].ToString() != panel.RetrievedManagedData[PKcol.ColumnName].ToString()) throw new WebDriverValidationException("The field '" + PKcol.ColumnName + "' is a part of the item`s identity and cannot be changed unless the item is recreated."); } try { driver.BeginTransaction(); int affected = driver.query("UPDATE " + panel.tableName + " SET ", dbe.UpdVals(panel.RetrievedInsertData), " WHERE ", dbe.Condition(panel.PK)); if (affected > 1) { driver.RollbackTransaction(); throw new Exception("Panel PK not unique, trying to update multiple rows at a time!"); } driver.CommitTransaction(); } catch (ConstraintException ce) { driver.RollbackTransaction(); throw new ConstraintException(FriendlyConstraintException(ce.Message, panel), null); } foreach (IField f in panel.fields) { if (f is M2NMappingField) { M2NMappingField m2nf = (M2NMappingField)f; int ID = (int)panel.PK[m2nf.Mapping.myColumn]; UnmapM2NMappingKey(m2nf.Mapping, ID); MapM2NVals(m2nf.Mapping, ID, (List<int>)m2nf.Data); } } }
void CreateWebControlsForPanel(MPanel activePanel, System.Web.UI.WebControls.Panel containerPanel) { List<BaseValidator> validators = new List<BaseValidator>(); validationSummary = new ValidationSummary(); validationSummary.BorderWidth = 0; MainPanel.Controls.Add(validationSummary); // no data in active panel => have to fill it if (!Page.IsPostBack || noSessionForActPanel) { if (CE.GlobalState == GlobalState.Architect) { foreach (IField field in activePanel.fields) { field.InventData(); } foreach (_min.Models.Control c in activePanel.controls) { c.InventData(); } } else { mm.WebDriver.FillPanelFKOptions(activePanel); if (activePanel.PK != null || activePanel.type != PanelTypes.Editable) try { mm.WebDriver.FillPanel(activePanel); } catch (WebDriverDataModificationException me) { // the row with the corresponding PK had been deleted in the meantime _min.Common.ValidationError.Display(me.Message, Page); } } } if (activePanel.type == PanelTypes.Editable) { // create a table with fields and captions tod display Table tbl = new Table(); tbl.CssClass = "formTbl"; foreach (IField f in activePanel.fields) { if (activePanel.PK == null && !Page.IsPostBack) f.Data = null; //if (f.type == FieldTypes.Holder) throw new NotImplementedException("Holder fields not yet supported in UI"); TableRow row = new TableRow(); TableCell captionCell = new TableCell(); Label caption = new Label(); caption.Text = f.Caption; captionCell.Controls.Add(caption); row.Cells.Add(captionCell); TableCell fieldCell = new TableCell(); System.Web.UI.WebControls.WebControl c = f.MyControl; validators.AddRange(f.GetValidators()); foreach (BaseValidator v in validators) { this.Form.Controls.Add(v); } fieldCell.Controls.Add(c); row.Cells.Add(fieldCell); tbl.Rows.Add(row); } MainPanel.Controls.Add(tbl); } // add the Constrols foreach (_min.Models.Control control in activePanel.controls) { if (control is TreeControl) { ((TreeControl)control).ToUControl(containerPanel, navigator.TreeHandler); } else if (control is NavTableControl) { // it is a mere gridview of a summary panel NavTableControl ntc = (NavTableControl)control; ntc.ToUControl(containerPanel, new GridViewCommandEventHandler(GridCommandEventHandler), GridView_PageIndexChanging, GridView_Sorting); } else // a simple Button or alike { if ((control.action == UserAction.Update || control.action == UserAction.Delete) && Page.Request.QueryString.Count == 0) continue; control.ToUControl(containerPanel, (CommandEventHandler)UserActionCommandHandler); } // not GridViewCommandEventHandler } foreach (BaseValidator validator in validators) { MainPanel.Controls.Add(validator); } // set the webcontrols from the stored value (initially null) foreach (_min.Interfaces.IField f in activePanel.fields) { f.FillData(); } }
/// <summary> /// Provides the Constraint exception thrown by MySQL command because of multi-column unique index with a less database-like message, /// does not modify it directly /// </summary> /// <param name="originalMessage"></param> /// <param name="panel"></param> /// <returns>the modified string</returns> private string FriendlyConstraintException(string originalMessage, Panel panel) { string newMessage = originalMessage; foreach (IField f in panel.fields) { if(f is IColumnField) newMessage = newMessage.Replace("'" + ((IColumnField)f).ColumnName + "'", "\"" + ((IColumnField)f).Caption + "\""); } return newMessage; }
protected void Page_Init(object sender, EventArgs e) { mm = (MinMaster)Master; navigator = new Navigator(Page); // whether in a specific panel or not, we need a menu MenuEventHandler menuHandler = navigator.MenuHandle; ((TreeControl)mm.SysDriver.MainPanel.controls[0]).ToUControl(MainPanel, navigator.MenuHandler); // get the active panel, if exists if (Page.RouteData.Values.ContainsKey("panelId") && Page.RouteData.Values["panelId"].ToString() == "0") { Page.RouteData.Values.Remove("panelId"); } if (Page.RouteData.Values.ContainsKey("panelId")) { // the basic panel if (Page.IsPostBack && Session[CC.SESSION_ACTIVE_PANEL] is MPanel) { activePanel = (MPanel)Session[CC.SESSION_ACTIVE_PANEL]; } else { noSessionForActPanel = true; Session[CC.SESSION_ACTIVE_PANEL] = null; activePanel = mm.SysDriver.Panels[Int32.Parse(Page.RouteData.Values["panelId"].ToString())]; } if (activePanel.isBaseNavPanel) { Response.RedirectToRoute( CE.GlobalState == GlobalState.Architect ? "ArchitectShowRoute" : "AdministerBrowseRoute", new { projectName = CE.project.Name }); return; } // panels is focused to a certain item (row in table) if (Request.QueryString.Count > 0) { SetRoutedPKForPanel(activePanel, Request.QueryString); } else { activePanel.PK = null; } // which action on this panel leads where var controlTargetPanels = from _min.Models.Control c in activePanel.controls select c.ActionsDicitionary; Dictionary <UserAction, int> currentPanelActionPanels = new Dictionary <UserAction, int>(); foreach (var x in controlTargetPanels) { foreach (KeyValuePair <UserAction, int> item in x) { if (!currentPanelActionPanels.ContainsKey(item.Key)) // should be done differently { currentPanelActionPanels.Add(item.Key, item.Value); } } } navigator.setCurrentTableActionPanels(currentPanelActionPanels); CreatePanelHeading(MainPanel); CreateWebControlsForPanel(activePanel, MainPanel); } else { CreatePanelHeading(MainPanel); } }
/// <summary> /// Fills panel with data based on the columns included and possibly the Primary Key /// </summary> /// <param name="panel"></param> public void FillPanel(Panel panel) { if (panel.fields.Count() > 0) { // editable Panel, fetch the DataRow, simple controls - must have unique PK var columns = panel.fields.Where(x => x is IColumnField).Select(x => ((IColumnField)x).ColumnName).ToList<string>(); DataTable table = driver.fetchAll("SELECT ", dbe.Cols(columns), " FROM ", panel.tableName, "WHERE", dbe.Condition(panel.PK)); if (table.Rows.Count > 1) throw new Exception("PK is not unique"); if (table.Rows.Count == 0) throw new WebDriverDataModificationException( "No data fulfill the condition. The record may have been removed."); DataRow row = table.Rows[0]; panel.OriginalData = table.Rows[0]; foreach (IField field in panel.fields) // fill the fields { if (field is IColumnField) { // value IColumnField cf = (IColumnField)field; cf.Data = row[cf.ColumnName].GetType() != typeof(MySql.Data.Types.MySqlDateTime) ? row[cf.ColumnName] : ((MySql.Data.Types.MySqlDateTime)row[cf.ColumnName]).GetDateTime(); } else { // mapping values are yet to fetch M2NMappingField m2nf = (M2NMappingField)field; m2nf.Data = FetchMappingValues(m2nf.Mapping, (int)panel.PK[0]); } } } foreach (Control c in panel.controls) { if (c is NavTableControl) { AssignDataForNavTable((NavTableControl)c, false); } // always gets the whole table, save in session else if (c is TreeControl && c.data is DataTable) { // there are no data in storedHierarchy - that is only the case of menu in base panel - fill it TreeControl tc = (TreeControl)c; tc.data.DataSet.EnforceConstraints = false; tc.data.Rows.Clear(); HierarchyNavTable hierarchy = (HierarchyNavTable)(tc.data); List<IDbCol> selectCols = new List<IDbCol>(); // don`t need to use constants - the column names are set in HierarchNavTable DataTable fetched = driver.fetchAll("SELECT", dbe.Col(tc.PKColNames[0], "Id"), ",", dbe.Cols(selectCols), dbe.Col(tc.parentColName, "ParentId"), ",", "CAST(", dbe.Col(tc.displayColName), "AS CHAR) AS \"Caption\"", ",", dbe.Col(tc.PKColNames[0], "NavId"), "FROM", panel.tableName); hierarchy.Merge(fetched); tc.data.DataSet.EnforceConstraints = true; } } /* foreach (Panel p in panel.children) FillPanel(p); */ }
/// <summary> /// Saves the panel to the system database, but doesn`t save the filds / controls (so that they can be saved in "next wave", after the panel ID is known /// and the the control target panel can be bound to the new panel via this ID /// </summary> /// <param name="panel"></param> /// <param name="recursive"></param> private void AddPanelOnly(Panel panel, bool recursive = true) { Dictionary<string, object> insertVals = new Dictionary<string, object>(); insertVals["content"] = panel.Serialize(); insertVals["id_project"] = CE.project.Id; if (panel.parent != null) insertVals["id_parent"] = panel.parent.panelId; if (!driver.IsInTransaction) { driver.BeginTransaction(); driver.query("INSERT INTO", dbe.Table("panels"), dbe.InsVals(insertVals)); panel.SetCreationId(driver.LastId()); driver.CommitTransaction(); } else { driver.query("INSERT INTO", dbe.Table("panels"), dbe.InsVals(insertVals)); panel.SetCreationId(driver.LastId()); } if (recursive) foreach (Panel child in panel.children) AddPanelOnly(child); }
void CreateWebControlsForPanel(MPanel activePanel, System.Web.UI.WebControls.Panel containerPanel) { List <BaseValidator> validators = new List <BaseValidator>(); validationSummary = new ValidationSummary(); validationSummary.BorderWidth = 0; MainPanel.Controls.Add(validationSummary); // no data in active panel => have to fill it if (!Page.IsPostBack || noSessionForActPanel) { if (CE.GlobalState == GlobalState.Architect) { foreach (IField field in activePanel.fields) { field.InventData(); } foreach (_min.Models.Control c in activePanel.controls) { c.InventData(); } } else { mm.WebDriver.FillPanelFKOptions(activePanel); if (activePanel.PK != null || activePanel.type != PanelTypes.Editable) { try { mm.WebDriver.FillPanel(activePanel); } catch (WebDriverDataModificationException me) { // the row with the corresponding PK had been deleted in the meantime _min.Common.ValidationError.Display(me.Message, Page); } } } } if (activePanel.type == PanelTypes.Editable) { // create a table with fields and captions tod display Table tbl = new Table(); tbl.CssClass = "formTbl"; foreach (IField f in activePanel.fields) { if (activePanel.PK == null && !Page.IsPostBack) { f.Data = null; } //if (f.type == FieldTypes.Holder) throw new NotImplementedException("Holder fields not yet supported in UI"); TableRow row = new TableRow(); TableCell captionCell = new TableCell(); Label caption = new Label(); caption.Text = f.Caption; captionCell.Controls.Add(caption); row.Cells.Add(captionCell); TableCell fieldCell = new TableCell(); System.Web.UI.WebControls.WebControl c = f.MyControl; validators.AddRange(f.GetValidators()); foreach (BaseValidator v in validators) { this.Form.Controls.Add(v); } fieldCell.Controls.Add(c); row.Cells.Add(fieldCell); tbl.Rows.Add(row); } MainPanel.Controls.Add(tbl); } // add the Constrols foreach (_min.Models.Control control in activePanel.controls) { if (control is TreeControl) { ((TreeControl)control).ToUControl(containerPanel, navigator.TreeHandler); } else if (control is NavTableControl) { // it is a mere gridview of a summary panel NavTableControl ntc = (NavTableControl)control; ntc.ToUControl(containerPanel, new GridViewCommandEventHandler(GridCommandEventHandler), GridView_PageIndexChanging, GridView_Sorting); } else // a simple Button or alike { if ((control.action == UserAction.Update || control.action == UserAction.Delete) && Page.Request.QueryString.Count == 0) { continue; } control.ToUControl(containerPanel, (CommandEventHandler)UserActionCommandHandler); } // not GridViewCommandEventHandler } foreach (BaseValidator validator in validators) { MainPanel.Controls.Add(validator); } // set the webcontrols from the stored value (initially null) foreach (_min.Interfaces.IField f in activePanel.fields) { f.FillData(); } }
private void FlattenPanel(Panel parentPanel) { Panels[parentPanel.panelId] = parentPanel; foreach (Panel p in parentPanel.children) FlattenPanel(p); }
/// <summary> /// Saves an existing panel to the database, rewriting the original attributes and all the fields and controls (including those that haven`t changed), /// </summary> /// <param name="panel"></param> /// <param name="recursive"></param> public void UpdatePanel(Panel panel, bool recursive = true) { Dictionary<string, object> updateVals = new Dictionary<string, object>(); if (panel.parent != null) updateVals["id_parent"] = panel.parent.panelId; updateVals["content"] = panel.Serialize(); driver.query("UPDATE panels SET", dbe.UpdVals(updateVals), "WHERE ", dbe.Col("id_panel"), " = ", panel.panelId); driver.query("DELETE FROM", dbe.Table("fields"), "WHERE", dbe.Col("id_panel"), " = ", panel.panelId); foreach (IField field in panel.fields) { AddField(field); } driver.query("DELETE FROM ", dbe.Table("controls"), " WHERE ", dbe.Col("id_panel"), " = ", panel.panelId); foreach (Control control in panel.controls) { AddControl(control); } if (recursive) { foreach (Panel child in panel.children) UpdatePanel(child, true); } }
protected void SaveButton_Click(object sender, EventArgs e) { string panelName = PanelName.Text; List <string> displayCols = DisplayCols.RetrieveStringData(); List <UserAction> actions = new List <UserAction>(); foreach (string s in actionsControl.RetrieveStringData()) { actions.Add((UserAction)Enum.Parse(typeof(UserAction), s)); } ValidationResult.Items.Clear(); // validate the proposal if (panelName == ".") { ValidationResult.Items.Add("Give the pannel a name, please."); } else if (displayCols.Count == 0) { ValidationResult.Items.Add("Select at leas one column to display"); } else if (actions.Count == 0) { ValidationResult.Items.Add("Check at least one action users can perform in thie panel, please"); } else { ValidationResult.Items.Add("Valid"); // => create the panel and save it _min.Models.Control c; List <_min.Models.Control> controls = new List <_min.Models.Control>(); _min.Models.Control insertButton = null; // insert is a separate button if (actions.Contains(UserAction.Insert)) { insertButton = new _min.Models.Control(actPanel.panelId, "Insert", UserAction.Insert); actions.Remove(UserAction.Insert); } // it is a NavTable if (NavControlType.SelectedValue.EndsWith("Table")) { List <FK> neededFKs = (from FK fk in FKs where displayCols.Contains(fk.myColumn) select fk).ToList <FK>(); c = new NavTableControl(actPanel.panelId, new System.Data.DataTable(), mm.Stats.PKs[actPanel.tableName], neededFKs, actions); c.displayColumns = displayCols; } else // NavTree { actions.Remove(UserAction.Delete); // cannot use delete in NavTrees c = new TreeControl(actPanel.panelId, new HierarchyNavTable(), mm.Stats.PKs[actPanel.tableName][0], hierarchy.myColumn, displayCols[0], actions); } controls.Add(c); if (insertButton != null) { controls.Add(insertButton); } foreach (_min.Models.Control listedControl in controls) { listedControl.targetPanelId = actPanel.controls[0].targetPanelId; } MPanel resPanel = new MPanel(actPanel.tableName, actPanel.panelId, c is TreeControl ? PanelTypes.NavTree : PanelTypes.NavTable, new List <MPanel>(), new List <IField>(), controls, actPanel.PKColNames, null, actPanel.parent); resPanel.panelName = panelName; actPanel = resPanel; mm.SysDriver.BeginTransaction(); mm.SysDriver.UpdatePanel(actPanel); mm.SysDriver.CommitTransaction(); mm.SysDriver.IncreaseVersionNumber(); ValidationResult.Items.Add("Saved"); Response.Redirect(Page.Request.RawUrl); } }
/// <summary> /// Initializes basic environment - Project, SystemDriver (contains architecture - all the panels linked in a tree), architect, stats, webDriver; /// sets the panel PK (if present), creates basic dropdown menu and lets the WebControls of the wohole rest of the page be created /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Init(object sender, EventArgs e) { mm = (MinMaster)Master; navigator = new Navigator(Page); // whether in a specific panel or not, we need a menu /**/ MenuEventHandler menuHandler = navigator.MenuHandle; ((TreeControl)mm.SysDriver.MainPanel.controls[0]).ToUControl(MainPanel, navigator.MenuHandler); /**/ // get the active panel, if exists if (Page.RouteData.Values.ContainsKey("panelId") && Page.RouteData.Values["panelId"].ToString() == "0") Page.RouteData.Values.Remove("panelId"); if (Page.RouteData.Values.ContainsKey("panelId")) { // the basic panel if (Page.IsPostBack && Session[CC.SESSION_ACTIVE_PANEL] is MPanel) { activePanel = (MPanel)Session[CC.SESSION_ACTIVE_PANEL]; } else { noSessionForActPanel = true; Session[CC.SESSION_ACTIVE_PANEL] = null; activePanel = mm.SysDriver.Panels[Int32.Parse(Page.RouteData.Values["panelId"].ToString())]; } if (activePanel.isBaseNavPanel) { Response.RedirectToRoute( CE.GlobalState == GlobalState.Architect ? "ArchitectShowRoute" : "AdministerBrowseRoute", new { projectName = CE.project.Name }); return; } // panels is focused to a certain item (row in table) if (Request.QueryString.Count > 0) { SetRoutedPKForPanel(activePanel, Request.QueryString); } else { activePanel.PK = null; } // which action on this panel leads where var controlTargetPanels = from _min.Models.Control c in activePanel.controls select c.ActionsDicitionary; Dictionary<UserAction, int> currentPanelActionPanels = new Dictionary<UserAction, int>(); foreach (var x in controlTargetPanels) { foreach (KeyValuePair<UserAction, int> item in x) { if (!currentPanelActionPanels.ContainsKey(item.Key)) // should be done differently currentPanelActionPanels.Add(item.Key, item.Value); } } navigator.setCurrentTableActionPanels(currentPanelActionPanels); CreatePanelHeading(MainPanel); CreateWebControlsForPanel(activePanel, MainPanel); } else { CreatePanelHeading(MainPanel); } }
/// <summary> /// Saves the controls within a panel and/or its childrent to the database; this is done after the control target panel ID has been set /// </summary> /// <param name="panel"></param> /// <param name="recursive"></param> private void AddPanelControlsOnly(Panel panel, bool recursive = true) { foreach (Control control in panel.controls) { control.RefreshPanelId(); AddControl(control); } if (recursive) foreach (Panel child in panel.children) AddPanelControlsOnly(child); }
private bool ServerValidate(MPanel panel) { bool valid = true; foreach (_min.Interfaces.IField f in panel.fields) { f.Validate(); if(f.ErrorMessage != null){ valid = false; _min.Common.ValidationError.Display(f.ErrorMessage, Page); } } return valid; }
// not relly needed (unike AddPanelControlsOnly), just for the sake of unified pattern /// <summary> /// Saves the fields within a panels and/or its children to the system database /// </summary> /// <param name="panel"></param> /// <param name="recursive"></param> private void AddPanelFieldsOnly(Panel panel, bool recursive = true) { foreach (IField field in panel.fields) { field.RefreshPanelId(); AddField(field); } if(recursive) foreach (Panel child in panel.children) AddPanelFieldsOnly(child); }