// SearchDashboards search dashboards by substring of their title. It allows restrict the result set with
// only starred dashboards and only for tags (logical OR applied to multiple tags).
429434
func (r *Client) SearchDashboards(query string, starred bool, tags ...string) ([]FoundBoard, error) {
	var (
		raw    []byte
		boards []FoundBoard
		code   int
		err    error
	)
	u := url.URL{}
	q := u.Query()
	if query != "" {
		q.Set("query", query)
	}
	if starred {
		q.Set("starred", "true")
	}
	for _, tag := range tags {
		q.Add("tag", tag)
	}
	if raw, code, err = r.get("api/search", q); err != nil {
		return nil, err
	}
	if code != 200 {
		return nil, fmt.Errorf("HTTP error %d: returns %s", code, raw)
	}
	err = json.Unmarshal(raw, &boards)
	return boards, err
}
919787
func MarshalDashboard(d chronograf.Dashboard) ([]byte, error) {
	cells := make([]*DashboardCell, len(d.Cells))
	for i, c := range d.Cells {
		queries := make([]*Query, len(c.Queries))
		for j, q := range c.Queries {
			r := new(Range)
			if q.Range != nil {
				r.Upper, r.Lower = q.Range.Upper, q.Range.Lower
			}
			q.Shifts = q.QueryConfig.Shifts
			queries[j] = &Query{
				Command: q.Command,
				Label:   q.Label,
				Range:   r,
				Source:  q.Source,
			}

			shifts := make([]*TimeShift, len(q.Shifts))
			for k := range q.Shifts {
				shift := &TimeShift{
					Label:    q.Shifts[k].Label,
					Unit:     q.Shifts[k].Unit,
					Quantity: q.Shifts[k].Quantity,
				}

				shifts[k] = shift
			}

			queries[j].Shifts = shifts
		}

		colors := make([]*Color, len(c.CellColors))
		for j, color := range c.CellColors {
			colors[j] = &Color{
				ID:    color.ID,
				Type:  color.Type,
				Hex:   color.Hex,
				Name:  color.Name,
				Value: color.Value,
			}
		}

		axes := make(map[string]*Axis, len(c.Axes))
		for a, r := range c.Axes {
			axes[a] = &Axis{
				Bounds: r.Bounds,
				Label:  r.Label,
				Prefix: r.Prefix,
				Suffix: r.Suffix,
				Base:   r.Base,
				Scale:  r.Scale,
			}
		}

		sortBy := &RenamableField{
			InternalName: c.TableOptions.SortBy.InternalName,
			DisplayName:  c.TableOptions.SortBy.DisplayName,
			Visible:      c.TableOptions.SortBy.Visible,
		}

		tableOptions := &TableOptions{
			VerticalTimeAxis: c.TableOptions.VerticalTimeAxis,
			SortBy:           sortBy,
			Wrapping:         c.TableOptions.Wrapping,
			FixFirstColumn:   c.TableOptions.FixFirstColumn,
		}

		decimalPlaces := &DecimalPlaces{
			IsEnforced: c.DecimalPlaces.IsEnforced,
			Digits:     c.DecimalPlaces.Digits,
		}

		fieldOptions := make([]*RenamableField, len(c.FieldOptions))
		for i, field := range c.FieldOptions {
			fieldOptions[i] = &RenamableField{
				InternalName: field.InternalName,
				DisplayName:  field.DisplayName,
				Visible:      field.Visible,
			}
		}

		cells[i] = &DashboardCell{
			ID:      c.ID,
			X:       c.X,
			Y:       c.Y,
			W:       c.W,
			H:       c.H,
			Name:    c.Name,
			Queries: queries,
			Type:    c.Type,
			Axes:    axes,
			Colors:  colors,
			Legend: &Legend{
				Type:        c.Legend.Type,
				Orientation: c.Legend.Orientation,
			},
			TableOptions:  tableOptions,
			FieldOptions:  fieldOptions,
			TimeFormat:    c.TimeFormat,
			DecimalPlaces: decimalPlaces,
		}
	}
	templates := make([]*Template, len(d.Templates))
	for i, t := range d.Templates {
		vals := make([]*TemplateValue, len(t.Values))
		for j, v := range t.Values {
			vals[j] = &TemplateValue{
				Selected: v.Selected,
				Type:     v.Type,
				Value:    v.Value,
				Key:      v.Key,
			}
		}

		template := &Template{
			ID:      string(t.ID),
			TempVar: t.Var,
			Values:  vals,
			Type:    t.Type,
			Label:   t.Label,
		}
		if t.Query != nil {
			template.Query = &TemplateQuery{
				Command:     t.Query.Command,
				Db:          t.Query.DB,
				Rp:          t.Query.RP,
				Measurement: t.Query.Measurement,
				TagKey:      t.Query.TagKey,
				FieldKey:    t.Query.FieldKey,
			}
		}
		templates[i] = template
	}
	return proto.Marshal(&Dashboard{
		ID:           int64(d.ID),
		Cells:        cells,
		Templates:    templates,
		Name:         d.Name,
		Organization: d.Organization,
	})
}
445855
func GetDashboardVersion(query *m.GetDashboardVersionQuery) error {
	version := m.DashboardVersion{}
	has, err := x.Where("dashboard_version.dashboard_id=? AND dashboard_version.version=? AND dashboard.org_id=?", query.DashboardId, query.Version, query.OrgId).
		Join("LEFT", "dashboard", `dashboard.id = dashboard_version.dashboard_id`).
		Get(&version)

	if err != nil {
		return err
	}

	if !has {
		return m.ErrDashboardVersionNotFound
	}

	version.Data.Set("id", version.DashboardId)
	query.Result = &version
	return nil
}
1238119
func (s *Service) GetDashboardCellView(ctx context.Context, dashboardID, cellID platform.ID) (*platform.View, error) {
	v, err := s.FindViewByID(ctx, cellID)
	if err != nil {
		return nil, &platform.Error{
			Err: err,
			Op:  OpPrefix + platform.OpGetDashboardCellView,
		}
	}

	return v, nil
}
915558
func (h *DashboardHandler) handleGetDashboards(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	req, err := decodeGetDashboardsRequest(ctx, r)
	if err != nil {
		EncodeError(ctx, err, w)
		return
	}

	if req.ownerID != nil {
		filter := platform.UserResourceMappingFilter{
			UserID:       *req.ownerID,
			UserType:     platform.Owner,
			ResourceType: platform.DashboardsResourceType,
		}

		mappings, _, err := h.UserResourceMappingService.FindUserResourceMappings(ctx, filter)
		if err != nil {
			EncodeError(ctx, &platform.Error{
				Code: platform.EInternal,
				Msg:  "Error loading dashboard owners",
				Err:  err,
			}, w)
			return
		}

		for _, mapping := range mappings {
			req.filter.IDs = append(req.filter.IDs, &mapping.ResourceID)
		}
	}

	dashboards, _, err := h.DashboardService.FindDashboards(ctx, req.filter, req.opts)
	if err != nil {
		EncodeError(ctx, err, w)
		return
	}

	if err := encodeResponse(ctx, w, http.StatusOK, newGetDashboardsResponse(ctx, dashboards, req.filter, req.opts, h.LabelService)); err != nil {
		logEncodingError(h.Logger, r, err)
		return
	}
}
643209
func (s *ProjectsService) ListDashboards(projectName string) (*[]DashboardInfo, *Response, error) {
	u := fmt.Sprintf("projects/%s/dashboards/", url.QueryEscape(projectName))

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	v := new([]DashboardInfo)
	resp, err := s.client.Do(req, v)
	if err != nil {
		return nil, resp, err
	}

	return v, resp, err
}
1323835
func (c *Client) GetDashboardOperationLog(ctx context.Context, id platform.ID, opts platform.FindOptions) ([]*platform.OperationLogEntry, int, error) {
	// TODO(desa): might be worthwhile to allocate a slice of size opts.Limit
	log := []*platform.OperationLogEntry{}

	err := c.db.View(func(tx *bolt.Tx) error {
		key, err := encodeDashboardOperationLogKey(id)
		if err != nil {
			return err
		}

		return c.forEachLogEntry(ctx, tx, key, opts, func(v []byte, t time.Time) error {
			e := &platform.OperationLogEntry{}
			if err := json.Unmarshal(v, e); err != nil {
				return err
			}
			e.Time = t

			log = append(log, e)

			return nil
		})
	})

	if err != nil {
		return nil, 0, err
	}

	return log, len(log), nil
}
982512
func SetupDashboard(Admin *admin.Admin) {
	// Add Dashboard
	Admin.AddMenu(&admin.Menu{Name: "Dashboard", Link: "/admin", Priority: 1})

	Admin.GetRouter().Get("/reports", ReportsDataHandler)
	initFuncMap(Admin)
}
173987
func NewDashboardService() *DashboardService {
	return &DashboardService{
		CreateDashboardF:   func(context.Context, *platform.Dashboard) error { return nil },
		FindDashboardByIDF: func(context.Context, platform.ID) (*platform.Dashboard, error) { return nil, nil },
		FindDashboardsF: func(context.Context, platform.DashboardFilter, platform.FindOptions) ([]*platform.Dashboard, int, error) {
			return nil, 0, nil
		},
		UpdateDashboardF: func(context.Context, platform.ID, platform.DashboardUpdate) (*platform.Dashboard, error) {
			return nil, nil
		},
		DeleteDashboardF: func(context.Context, platform.ID) error { return nil },

		AddDashboardCellF: func(ctx context.Context, id platform.ID, c *platform.Cell, opts platform.AddDashboardCellOptions) error {
			return nil
		},
		RemoveDashboardCellF: func(ctx context.Context, dashboardID platform.ID, cellID platform.ID) error { return nil },
		GetDashboardCellViewF: func(ctx context.Context, dashboardID platform.ID, cellID platform.ID) (*platform.View, error) {
			return nil, nil
		},
		UpdateDashboardCellViewF: func(ctx context.Context, dashboardID platform.ID, cellID platform.ID, upd platform.ViewUpdate) (*platform.View, error) {
			return nil, nil
		},
		UpdateDashboardCellF: func(ctx context.Context, dashbaordID platform.ID, cellID platform.ID, upd platform.CellUpdate) (*platform.Cell, error) {
			return nil, nil
		},
		CopyDashboardCellF: func(ctx context.Context, dashbaordID platform.ID, cellID platform.ID) (*platform.Cell, error) {
			return nil, nil
		},
		ReplaceDashboardCellsF: func(ctx context.Context, id platform.ID, cs []*platform.Cell) error { return nil },
	}
}
973545
func (s *Service) FindDashboards(ctx context.Context, filter platform.DashboardFilter, opts platform.FindOptions) ([]*platform.Dashboard, int, error) {
	var ds []*platform.Dashboard
	op := OpPrefix + platform.OpFindDashboards
	if len(filter.IDs) == 1 {
		d, err := s.FindDashboardByID(ctx, *filter.IDs[0])
		if err != nil && platform.ErrorCode(err) != platform.ENotFound {
			return ds, 0, &platform.Error{
				Err: err,
				Op:  op,
			}
		}
		if d == nil {
			return ds, 0, nil
		}
		return []*platform.Dashboard{d}, 1, nil
	}

	var count int
	filterFn := filterDashboardFn(filter)
	err := s.forEachDashboard(ctx, opts, func(d *platform.Dashboard) bool {
		if filterFn(d) {
			if count >= opts.Offset {
				ds = append(ds, d)
			}
			count++
		}
		if opts.Limit > 0 && len(ds) >= opts.Limit {
			return false
		}
		return true
	})

	if err != nil {
		return nil, 0, err
	}

	return ds, len(ds), err
}
180152
func (h *DashboardHandler) handlePostDashboard(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	req, err := decodePostDashboardRequest(ctx, r)
	if err != nil {
		EncodeError(ctx, err, w)
		return
	}
	if err := h.DashboardService.CreateDashboard(ctx, req.Dashboard); err != nil {
		EncodeError(ctx, errors.InternalErrorf("Error loading dashboards: %v", err), w)
		return
	}

	if err := encodeResponse(ctx, w, http.StatusCreated, newDashboardResponse(req.Dashboard, []*platform.Label{})); err != nil {
		logEncodingError(h.Logger, r, err)
		return
	}
}
187072
func (w *wizard) deployDashboard() {
	// Select the server to interact with
	server := w.selectServer()
	if server == "" {
		return
	}
	client := w.servers[server]

	// Retrieve any active dashboard configurations from the server
	infos, err := checkDashboard(client, w.network)
	if err != nil {
		infos = &dashboardInfos{
			port: 80,
			host: client.server,
		}
	}
	existed := err == nil

	// Figure out which port to listen on
	fmt.Println()
	fmt.Printf("Which port should the dashboard listen on? (default = %d)\n", infos.port)
	infos.port = w.readDefaultInt(infos.port)

	// Figure which virtual-host to deploy the dashboard on
	infos.host, err = w.ensureVirtualHost(client, infos.port, infos.host)
	if err != nil {
		log.Error("Failed to decide on dashboard host", "err", err)
		return
	}
	// Port and proxy settings retrieved, figure out which services are available
	available := make(map[string][]string)
	for server, services := range w.services {
		for _, service := range services {
			available[service] = append(available[service], server)
		}
	}
	for _, service := range []string{"ethstats", "explorer", "wallet", "faucet"} {
		// Gather all the locally hosted pages of this type
		var pages []string
		for _, server := range available[service] {
			client := w.servers[server]
			if client == nil {
				continue
			}
			// If there's a service running on the machine, retrieve it's port number
			var port int
			switch service {
			case "ethstats":
				if infos, err := checkEthstats(client, w.network); err == nil {
					port = infos.port
				}
			case "explorer":
				if infos, err := checkExplorer(client, w.network); err == nil {
					port = infos.webPort
				}
			case "wallet":
				if infos, err := checkWallet(client, w.network); err == nil {
					port = infos.webPort
				}
			case "faucet":
				if infos, err := checkFaucet(client, w.network); err == nil {
					port = infos.port
				}
			}
			if page, err := resolve(client, w.network, service, port); err == nil && page != "" {
				pages = append(pages, page)
			}
		}
		// Prompt the user to chose one, enter manually or simply not list this service
		defLabel, defChoice := "don't list", len(pages)+2
		if len(pages) > 0 {
			defLabel, defChoice = pages[0], 1
		}
		fmt.Println()
		fmt.Printf("Which %s service to list? (default = %s)\n", service, defLabel)
		for i, page := range pages {
			fmt.Printf(" %d. %s\n", i+1, page)
		}
		fmt.Printf(" %d. List external %s service\n", len(pages)+1, service)
		fmt.Printf(" %d. Don't list any %s service\n", len(pages)+2, service)

		choice := w.readDefaultInt(defChoice)
		if choice < 0 || choice > len(pages)+2 {
			log.Error("Invalid listing choice, aborting")
			return
		}
		var page string
		switch {
		case choice <= len(pages):
			page = pages[choice-1]
		case choice == len(pages)+1:
			fmt.Println()
			fmt.Printf("Which address is the external %s service at?\n", service)
			page = w.readString()
		default:
			// No service hosting for this
		}
		// Save the users choice
		switch service {
		case "ethstats":
			infos.ethstats = page
		case "explorer":
			infos.explorer = page
		case "wallet":
			infos.wallet = page
		case "faucet":
			infos.faucet = page
		}
	}
	// If we have ethstats running, ask whether to make the secret public or not
	if w.conf.ethstats != "" {
		fmt.Println()
		fmt.Println("Include ethstats secret on dashboard (y/n)? (default = yes)")
		infos.trusted = w.readDefaultYesNo(true)
	}
	// Try to deploy the dashboard container on the host
	nocache := false
	if existed {
		fmt.Println()
		fmt.Printf("Should the dashboard be built from scratch (y/n)? (default = no)\n")
		nocache = w.readDefaultYesNo(false)
	}
	if out, err := deployDashboard(client, w.network, &w.conf, infos, nocache); err != nil {
		log.Error("Failed to deploy dashboard container", "err", err)
		if len(out) > 0 {
			fmt.Printf("%s\n", out)
		}
		return
	}
	// All ok, run a network scan to pick any changes up
	w.networkStats()
}
315691
func (s *Service) FindDashboard(ctx context.Context, filter influxdb.DashboardFilter, opts ...influxdb.FindOptions) (*influxdb.Dashboard, error) {
	if len(filter.IDs) == 1 {
		return s.FindDashboardByID(ctx, *filter.IDs[0])
	}

	var d *influxdb.Dashboard
	err := s.kv.View(ctx, func(tx Tx) error {
		filterFn := filterDashboardsFn(filter)
		return s.forEachDashboard(ctx, tx, opts[0].Descending, func(dash *influxdb.Dashboard) bool {
			if filterFn(dash) {
				d = dash
				return false
			}
			return true
		})
	})

	if err != nil {
		return nil, err
	}

	if d == nil {
		return nil, &influxdb.Error{
			Code: influxdb.ENotFound,
			Msg:  influxdb.ErrDashboardNotFound,
		}
	}

	return d, nil
}
727888
func (s *Service) ReplaceDashboard(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	idParam, err := paramID("id", r)
	if err != nil {
		msg := fmt.Sprintf("Could not parse dashboard ID: %s", err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
	}
	id := chronograf.DashboardID(idParam)

	_, err = s.Store.Dashboards(ctx).Get(ctx, id)
	if err != nil {
		Error(w, http.StatusNotFound, fmt.Sprintf("ID %d not found", id), s.Logger)
		return
	}

	var req chronograf.Dashboard
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		invalidJSON(w, s.Logger)
		return
	}
	req.ID = id

	defaultOrg, err := s.Store.Organizations(ctx).DefaultOrganization(ctx)
	if err != nil {
		unknownErrorWithMessage(w, err, s.Logger)
		return
	}

	if err := ValidDashboardRequest(&req, defaultOrg.ID); err != nil {
		invalidData(w, err, s.Logger)
		return
	}

	if err := s.Store.Dashboards(ctx).Update(ctx, req); err != nil {
		msg := fmt.Sprintf("Error updating dashboard ID %d: %v", id, err)
		Error(w, http.StatusInternalServerError, msg, s.Logger)
		return
	}

	res := newDashboardResponse(req)
	encodeJSON(w, http.StatusOK, res, s.Logger)
}
439889
func (s *Service) NewDashboard(w http.ResponseWriter, r *http.Request) {
	var dashboard chronograf.Dashboard
	var err error
	if err := json.NewDecoder(r.Body).Decode(&dashboard); err != nil {
		invalidJSON(w, s.Logger)
		return
	}

	ctx := r.Context()
	defaultOrg, err := s.Store.Organizations(ctx).DefaultOrganization(ctx)
	if err != nil {
		unknownErrorWithMessage(w, err, s.Logger)
		return
	}

	if err := ValidDashboardRequest(&dashboard, defaultOrg.ID); err != nil {
		invalidData(w, err, s.Logger)
		return
	}

	if dashboard, err = s.Store.Dashboards(ctx).Add(r.Context(), dashboard); err != nil {
		msg := fmt.Errorf("error storing dashboard %v: %v", dashboard, err)
		unknownErrorWithMessage(w, msg, s.Logger)
		return
	}

	res := newDashboardResponse(dashboard)
	location(w, res.Links.Self)
	encodeJSON(w, http.StatusCreated, res, s.Logger)
}
928261
func (c *Client) PutDashboard(ctx context.Context, d *platform.Dashboard) error {
	return c.db.Update(func(tx *bolt.Tx) error {
		for _, cell := range d.Cells {
			if err := c.createCellView(ctx, tx, d.ID, cell.ID, nil); err != nil {
				return err
			}
		}

		if err := c.putOrganizationDashboardIndex(ctx, tx, d); err != nil {
			return err
		}

		return c.putDashboard(ctx, tx, d)
	})
}
20040
func GetDashboardUrl(uid string, slug string) string {
	return fmt.Sprintf("%s/d/%s/%s", setting.AppSubUrl, uid, slug)
}