public object CreatePanel(HttpRequestParams request)
		{
			Guid dashboardId = request.GetRequiredGuid("dashboard");
			string title = request.GetRequiredString("title");

			using (var session = Context.OpenSession())
			{
				var dashboard = session.Load<Dashboard>(dashboardId);

				var panel = new Panel
				{
					Id = Guid.NewGuid(),
					Title = title,
					Dashboard = dashboard,
					SortOrder = int.MaxValue
				};

				session.Save(panel);
				session.Flush();

				return panel.Id;
			}
		}
		private object[] GetPanelListModel(Panel[] allPanels, Widget[] allWidgets, WidgetParameter[] allParameters, ISession session)
		{
			var list = new List<object>();

			foreach (var panel in allPanels)
			{
				var panelWidgets = allWidgets.Where(w => w.Panel.Id == panel.Id).ToArray();
				var widgetListModel = GetWidgetListModel(panelWidgets, allParameters, session);

				var model = new {
					id = panel.Id,
					title = panel.Title,
					widgets = widgetListModel,
					sortOrder = panel.SortOrder
				};

				list.Add(model);
			}

			return list.ToArray();
		}
		private Tuple<EditorModel, EditorParameterModel[]> GetEditorModel(
			string type, Panel panel, ISession session)
		{
			if (!defs.ContainsKey(type))
			{
				throw new Exception(string.Format("invalid widget type {0}", type));
			}

			var def = defs[type];

			var metaData = def.GetWidgetMetaData(session, Logger) 
				?? new WidgetParameterMetaData[0];

			var parameters = metaData
						.Select(GetEditorParameterModel)
						.ToArray();

			var model = new EditorModel
			{
				typeDisplayName = def.DisplayName,
				panelId = panel.Id,
				panelTitle = panel.Title,
				dashboardId = panel.Dashboard.Id,
				dashboardTitle = panel.Dashboard.Title,
				type = type
			};

			return new Tuple<EditorModel, EditorParameterModel[]>(model, parameters);
		}