1 |
- {"version":3,"file":"TeamPages.e119b2547fd7d5579f18.js","mappings":"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","sources":["webpack://grafana/./public/app/core/components/SharedPreferences/SharedPreferences.tsx","webpack://grafana/./public/app/features/teams/TeamGroupSync.tsx","webpack://grafana/./public/app/core/components/WithFeatureToggle.tsx","webpack://grafana/./public/app/features/teams/TeamMemberRow.tsx","webpack://grafana/./public/app/features/teams/TeamMembers.tsx","webpack://grafana/./public/app/features/teams/TeamPermissions.tsx","webpack://grafana/./public/app/features/teams/TeamSettings.tsx","webpack://grafana/./public/app/features/teams/TeamPages.tsx","webpack://grafana/./public/app/features/teams/state/actions.ts","webpack://grafana/./public/app/features/teams/state/navModel.ts","webpack://grafana/./public/app/features/teams/state/selectors.ts"],"sourcesContent":["import { css } from '@emotion/css';\nimport { t, Trans } from '@lingui/macro';\nimport React, { PureComponent } from 'react';\n\nimport { SelectableValue } from '@grafana/data';\nimport { selectors } from '@grafana/e2e-selectors';\nimport {\n Button,\n Field,\n FieldSet,\n Form,\n Icon,\n Label,\n RadioButtonGroup,\n Select,\n stylesFactory,\n TimeZonePicker,\n Tooltip,\n WeekStartPicker,\n} from '@grafana/ui';\nimport { PreferencesService } from 'app/core/services/PreferencesService';\nimport { backendSrv } from 'app/core/services/backend_srv';\nimport { DashboardSearchHit, DashboardSearchItemType } from 'app/features/search/types';\n\nimport { UserPreferencesDTO } from '../../../types';\n\nexport interface Props {\n resourceUri: string;\n disabled?: boolean;\n}\n\nexport type State = UserPreferencesDTO & {\n dashboards: DashboardSearchHit[];\n};\n\nconst themes: SelectableValue[] = [\n { value: '', label: t({ id: 'shared-preferences.theme.default-label', message: 'Default' }) },\n { value: 'dark', label: t({ id: 'shared-preferences.theme.dark-label', message: 'Dark' }) },\n { value: 'light', label: t({ id: 'shared-preferences.theme.light-label', message: 'Light' }) },\n];\n\nexport class SharedPreferences extends PureComponent<Props, State> {\n service: PreferencesService;\n\n constructor(props: Props) {\n super(props);\n\n this.service = new PreferencesService(props.resourceUri);\n this.state = {\n homeDashboardId: 0,\n theme: '',\n timezone: '',\n weekStart: '',\n dashboards: [],\n queryHistory: { homeTab: '' },\n };\n }\n\n async componentDidMount() {\n const prefs = await this.service.load();\n const dashboards = await backendSrv.search({ starred: true });\n const defaultDashboardHit: DashboardSearchHit = {\n id: 0,\n title: 'Default',\n tags: [],\n type: '' as DashboardSearchItemType,\n uid: '',\n uri: '',\n url: '',\n folderId: 0,\n folderTitle: '',\n folderUid: '',\n folderUrl: '',\n isStarred: false,\n slug: '',\n items: [],\n };\n\n if (prefs.homeDashboardId > 0 && !dashboards.find((d) => d.id === prefs.homeDashboardId)) {\n const missing = await backendSrv.search({ dashboardIds: [prefs.homeDashboardId] });\n if (missing && missing.length > 0) {\n dashboards.push(missing[0]);\n }\n }\n\n this.setState({\n homeDashboardId: prefs.homeDashboardId,\n theme: prefs.theme,\n timezone: prefs.timezone,\n weekStart: prefs.weekStart,\n dashboards: [defaultDashboardHit, ...dashboards],\n queryHistory: prefs.queryHistory,\n });\n }\n\n onSubmitForm = async () => {\n const { homeDashboardId, theme, timezone, weekStart, queryHistory } = this.state;\n await this.service.update({ homeDashboardId, theme, timezone, weekStart, queryHistory });\n window.location.reload();\n };\n\n onThemeChanged = (value: string) => {\n this.setState({ theme: value });\n };\n\n onTimeZoneChanged = (timezone?: string) => {\n if (!timezone) {\n return;\n }\n this.setState({ timezone: timezone });\n };\n\n onWeekStartChanged = (weekStart: string) => {\n this.setState({ weekStart: weekStart });\n };\n\n onHomeDashboardChanged = (dashboardId: number) => {\n this.setState({ homeDashboardId: dashboardId });\n };\n\n getFullDashName = (dashboard: SelectableValue<DashboardSearchHit>) => {\n if (typeof dashboard.folderTitle === 'undefined' || dashboard.folderTitle === '') {\n return dashboard.title;\n }\n return dashboard.folderTitle + ' / ' + dashboard.title;\n };\n\n render() {\n const { theme, timezone, weekStart, homeDashboardId, dashboards } = this.state;\n const { disabled } = this.props;\n const styles = getStyles();\n\n const homeDashboardTooltip = (\n <Tooltip\n content={\n <Trans id=\"shared-preferences.fields.home-dashboard-tooltip\">\n Not finding the dashboard you want? Star it first, then it should appear in this select box.\n </Trans>\n }\n >\n <Icon name=\"info-circle\" />\n </Tooltip>\n );\n\n return (\n <Form onSubmit={this.onSubmitForm}>\n {() => {\n return (\n <FieldSet label={<Trans id=\"shared-preferences.title\">Preferences</Trans>} disabled={disabled}>\n <Field label={t({ id: 'shared-preferences.fields.theme-label', message: 'UI Theme' })}>\n <RadioButtonGroup\n options={themes}\n value={themes.find((item) => item.value === theme)?.value}\n onChange={this.onThemeChanged}\n />\n </Field>\n\n <Field\n label={\n <Label htmlFor=\"home-dashboard-select\">\n <span className={styles.labelText}>\n <Trans id=\"shared-preferences.fields.home-dashboard-label\">Home Dashboard</Trans>\n </span>\n\n {homeDashboardTooltip}\n </Label>\n }\n data-testid=\"User preferences home dashboard drop down\"\n >\n <Select\n value={dashboards.find((dashboard) => dashboard.id === homeDashboardId)}\n getOptionValue={(i) => i.id}\n getOptionLabel={this.getFullDashName}\n onChange={(dashboard: SelectableValue<DashboardSearchHit>) =>\n this.onHomeDashboardChanged(dashboard.id)\n }\n options={dashboards}\n placeholder={t({\n id: 'shared-preferences.fields.home-dashboard-placeholder',\n message: 'Choose default dashboard',\n })}\n inputId=\"home-dashboard-select\"\n />\n </Field>\n\n <Field\n label={t({ id: 'shared-dashboard.fields.timezone-label', message: 'Timezone' })}\n data-testid={selectors.components.TimeZonePicker.containerV2}\n >\n <TimeZonePicker\n includeInternal={true}\n value={timezone}\n onChange={this.onTimeZoneChanged}\n inputId=\"shared-preferences-timezone-picker\"\n />\n </Field>\n\n <Field\n label={t({ id: 'shared-preferences.fields.week-start-label', message: 'Week start' })}\n data-testid={selectors.components.WeekStartPicker.containerV2}\n >\n <WeekStartPicker\n value={weekStart}\n onChange={this.onWeekStartChanged}\n inputId={'shared-preferences-week-start-picker'}\n />\n </Field>\n\n <div className=\"gf-form-button-row\">\n <Button\n type=\"submit\"\n variant=\"primary\"\n data-testid={selectors.components.UserProfile.preferencesSaveButton}\n >\n <Trans id=\"common.save\">Save</Trans>\n </Button>\n </div>\n </FieldSet>\n );\n }}\n </Form>\n );\n }\n}\n\nexport default SharedPreferences;\n\nconst getStyles = stylesFactory(() => {\n return {\n labelText: css`\n margin-right: 6px;\n `,\n };\n});\n","import React, { PureComponent } from 'react';\nimport { connect, ConnectedProps } from 'react-redux';\n\nimport { Input, Tooltip, Icon, Button, useTheme2, InlineField, InlineFieldRow } from '@grafana/ui';\nimport { SlideDown } from 'app/core/components/Animations/SlideDown';\nimport { CloseButton } from 'app/core/components/CloseButton/CloseButton';\nimport EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';\nimport { UpgradeBox, UpgradeContent, UpgradeContentProps } from 'app/core/components/Upgrade/UpgradeBox';\nimport { highlightTrial } from 'app/features/admin/utils';\n\nimport { StoreState, TeamGroup } from '../../types';\n\nimport { addTeamGroup, loadTeamGroups, removeTeamGroup } from './state/actions';\nimport { getTeamGroups } from './state/selectors';\n\nfunction mapStateToProps(state: StoreState) {\n return {\n groups: getTeamGroups(state.team),\n };\n}\n\nconst mapDispatchToProps = {\n loadTeamGroups,\n addTeamGroup,\n removeTeamGroup,\n};\n\ninterface OwnProps {\n isReadOnly: boolean;\n}\n\ninterface State {\n isAdding: boolean;\n newGroupId: string;\n}\n\nconst connector = connect(mapStateToProps, mapDispatchToProps);\nexport type Props = OwnProps & ConnectedProps<typeof connector>;\n\nconst headerTooltip = `Sync LDAP or OAuth groups with your Grafana teams.`;\n\nexport class TeamGroupSync extends PureComponent<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { isAdding: false, newGroupId: '' };\n }\n\n componentDidMount() {\n this.fetchTeamGroups();\n }\n\n async fetchTeamGroups() {\n await this.props.loadTeamGroups();\n }\n\n onToggleAdding = () => {\n this.setState({ isAdding: !this.state.isAdding });\n };\n\n onNewGroupIdChanged = (event: any) => {\n this.setState({ newGroupId: event.target.value });\n };\n\n onAddGroup = (event: any) => {\n event.preventDefault();\n this.props.addTeamGroup(this.state.newGroupId);\n this.setState({ isAdding: false, newGroupId: '' });\n };\n\n onRemoveGroup = (group: TeamGroup) => {\n this.props.removeTeamGroup(group.groupId);\n };\n\n isNewGroupValid() {\n return this.state.newGroupId.length > 1;\n }\n\n renderGroup(group: TeamGroup) {\n const { isReadOnly } = this.props;\n return (\n <tr key={group.groupId}>\n <td>{group.groupId}</td>\n <td style={{ width: '1%' }}>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => this.onRemoveGroup(group)}\n disabled={isReadOnly}\n aria-label={`Remove group ${group.groupId}`}\n >\n <Icon name=\"times\" />\n </Button>\n </td>\n </tr>\n );\n }\n\n render() {\n const { isAdding, newGroupId } = this.state;\n const { groups, isReadOnly } = this.props;\n return (\n <div>\n {highlightTrial() && (\n <UpgradeBox\n featureId={'team-sync'}\n eventVariant={'trial'}\n featureName={'team sync'}\n text={'Add a group to enable team sync for free during your trial of Grafana Pro.'}\n />\n )}\n <div className=\"page-action-bar\">\n {(!highlightTrial() || groups.length > 0) && (\n <>\n <h3 className=\"page-sub-heading\">External group sync</h3>\n <Tooltip placement=\"auto\" content={headerTooltip}>\n <Icon className=\"icon--has-hover page-sub-heading-icon\" name=\"question-circle\" />\n </Tooltip>\n </>\n )}\n <div className=\"page-action-bar__spacer\" />\n {groups.length > 0 && (\n <Button className=\"pull-right\" onClick={this.onToggleAdding} disabled={isReadOnly}>\n <Icon name=\"plus\" /> Add group\n </Button>\n )}\n </div>\n\n <SlideDown in={isAdding}>\n <div className=\"cta-form\">\n <CloseButton onClick={this.onToggleAdding} />\n <form onSubmit={this.onAddGroup}>\n <InlineFieldRow>\n <InlineField label={'Add External Group'}>\n <Input\n type=\"text\"\n id={'add-external-group'}\n value={newGroupId}\n onChange={this.onNewGroupIdChanged}\n placeholder=\"cn=ops,ou=groups,dc=grafana,dc=org\"\n disabled={isReadOnly}\n />\n </InlineField>\n\n <Button type=\"submit\" disabled={isReadOnly || !this.isNewGroupValid()} style={{ marginLeft: 4 }}>\n Add group\n </Button>\n </InlineFieldRow>\n </form>\n </div>\n </SlideDown>\n\n {groups.length === 0 &&\n !isAdding &&\n (highlightTrial() ? (\n <TeamSyncUpgradeContent action={{ onClick: this.onToggleAdding, text: 'Add group' }} />\n ) : (\n <EmptyListCTA\n onClick={this.onToggleAdding}\n buttonIcon=\"users-alt\"\n title=\"There are no external groups to sync with\"\n buttonTitle=\"Add group\"\n proTip={headerTooltip}\n proTipLinkTitle=\"Learn more\"\n proTipLink=\"https://docs.grafana.org/auth/enhanced_ldap/\"\n proTipTarget=\"_blank\"\n buttonDisabled={isReadOnly}\n />\n ))}\n\n {groups.length > 0 && (\n <div className=\"admin-list-table\">\n <table className=\"filter-table filter-table--hover form-inline\">\n <thead>\n <tr>\n <th>External Group ID</th>\n <th style={{ width: '1%' }} />\n </tr>\n </thead>\n <tbody>{groups.map((group) => this.renderGroup(group))}</tbody>\n </table>\n </div>\n )}\n </div>\n );\n }\n}\n\nexport const TeamSyncUpgradeContent = ({ action }: { action?: UpgradeContentProps['action'] }) => {\n const theme = useTheme2();\n return (\n <UpgradeContent\n action={action}\n listItems={[\n 'Stop managing user access in two places - assign users to groups in SAML, LDAP or Oauth, and manage access at a Team level in Grafana',\n 'Update users’ permissions immediately when you add or remove them from an LDAP group, with no need for them to sign out and back in',\n ]}\n image={`team-sync-${theme.isLight ? 'light' : 'dark'}.png`}\n featureName={'team sync'}\n featureUrl={'https://grafana.com/docs/grafana/latest/enterprise/team-sync'}\n description={\n 'Team Sync makes it easier for you to manage users’ access in Grafana, by immediately updating each user’s Grafana teams and permissions based on their single sign-on group membership, instead of when users sign in.'\n }\n />\n );\n};\nexport default connect(mapStateToProps, mapDispatchToProps)(TeamGroupSync);\n","import React, { FunctionComponent } from 'react';\n\nexport interface Props {\n featureToggle: boolean;\n}\n\nexport const WithFeatureToggle: FunctionComponent<Props> = ({ featureToggle, children }) => {\n if (featureToggle === true) {\n return <>{children}</>;\n }\n\n return null;\n};\n","import React, { PureComponent } from 'react';\nimport { connect, ConnectedProps } from 'react-redux';\n\nimport { SelectableValue } from '@grafana/data';\nimport { LegacyForms, DeleteButton } from '@grafana/ui';\nimport { TagBadge } from 'app/core/components/TagFilter/TagBadge';\nimport { WithFeatureToggle } from 'app/core/components/WithFeatureToggle';\nimport { TeamMember, teamsPermissionLevels, TeamPermissionLevel } from 'app/types';\n\nimport { updateTeamMember, removeTeamMember } from './state/actions';\n\nconst { Select } = LegacyForms;\n\nconst mapDispatchToProps = {\n removeTeamMember,\n updateTeamMember,\n};\n\nconst connector = connect(null, mapDispatchToProps);\n\ninterface OwnProps {\n member: TeamMember;\n syncEnabled: boolean;\n editorsCanAdmin: boolean;\n signedInUserIsTeamAdmin: boolean;\n}\nexport type Props = ConnectedProps<typeof connector> & OwnProps;\n\nexport class TeamMemberRow extends PureComponent<Props> {\n constructor(props: Props) {\n super(props);\n this.renderLabels = this.renderLabels.bind(this);\n this.renderPermissions = this.renderPermissions.bind(this);\n }\n\n onRemoveMember(member: TeamMember) {\n this.props.removeTeamMember(member.userId);\n }\n\n onPermissionChange = (item: SelectableValue<TeamPermissionLevel>, member: TeamMember) => {\n const permission = item.value;\n const updatedTeamMember: TeamMember = {\n ...member,\n permission: permission as number,\n };\n\n this.props.updateTeamMember(updatedTeamMember);\n };\n\n renderPermissions(member: TeamMember) {\n const { editorsCanAdmin, signedInUserIsTeamAdmin } = this.props;\n const value = teamsPermissionLevels.find((dp) => dp.value === member.permission)!;\n\n return (\n <WithFeatureToggle featureToggle={editorsCanAdmin}>\n <td className=\"width-5 team-permissions\">\n <div className=\"gf-form\">\n {signedInUserIsTeamAdmin && (\n <Select\n isSearchable={false}\n options={teamsPermissionLevels}\n onChange={(item) => this.onPermissionChange(item, member)}\n className=\"gf-form-select-box__control--menu-right\"\n value={value}\n />\n )}\n {!signedInUserIsTeamAdmin && <span>{value.label}</span>}\n </div>\n </td>\n </WithFeatureToggle>\n );\n }\n\n renderLabels(labels: string[]) {\n if (!labels) {\n return <td />;\n }\n\n return (\n <td>\n {labels.map((label) => (\n <TagBadge key={label} label={label} removeIcon={false} count={0} onClick={() => {}} />\n ))}\n </td>\n );\n }\n\n render() {\n const { member, syncEnabled, signedInUserIsTeamAdmin } = this.props;\n return (\n <tr key={member.userId}>\n <td className=\"width-4 text-center\">\n <img\n aria-label={`Avatar for team member \"${member.name}\"`}\n className=\"filter-table__avatar\"\n src={member.avatarUrl}\n />\n </td>\n <td>{member.login}</td>\n <td>{member.email}</td>\n <td>{member.name}</td>\n {this.renderPermissions(member)}\n {syncEnabled && this.renderLabels(member.labels)}\n <td className=\"text-right\">\n <DeleteButton\n aria-label=\"Remove team member\"\n size=\"sm\"\n disabled={!signedInUserIsTeamAdmin}\n onConfirm={() => this.onRemoveMember(member)}\n />\n </td>\n </tr>\n );\n }\n}\n\nexport default connector(TeamMemberRow);\n","import React, { PureComponent } from 'react';\nimport { connect, ConnectedProps } from 'react-redux';\n\nimport { SelectableValue } from '@grafana/data';\nimport { Button, FilterInput, Label } from '@grafana/ui';\nimport { SlideDown } from 'app/core/components/Animations/SlideDown';\nimport { CloseButton } from 'app/core/components/CloseButton/CloseButton';\nimport { UserPicker } from 'app/core/components/Select/UserPicker';\nimport { TagBadge } from 'app/core/components/TagFilter/TagBadge';\nimport { WithFeatureToggle } from 'app/core/components/WithFeatureToggle';\nimport { config } from 'app/core/config';\nimport { contextSrv } from 'app/core/services/context_srv';\nimport { TeamMember, OrgUser } from 'app/types';\n\nimport TeamMemberRow from './TeamMemberRow';\nimport { addTeamMember } from './state/actions';\nimport { setSearchMemberQuery } from './state/reducers';\nimport { getSearchMemberQuery, isSignedInUserTeamAdmin } from './state/selectors';\n\nfunction mapStateToProps(state: any) {\n return {\n searchMemberQuery: getSearchMemberQuery(state.team),\n editorsCanAdmin: config.editorsCanAdmin, // this makes the feature toggle mockable/controllable from tests,\n signedInUser: contextSrv.user, // this makes the feature toggle mockable/controllable from tests,\n };\n}\n\nconst mapDispatchToProps = {\n addTeamMember,\n setSearchMemberQuery,\n};\n\nconst connector = connect(mapStateToProps, mapDispatchToProps);\n\ninterface OwnProps {\n members: TeamMember[];\n syncEnabled: boolean;\n}\n\nexport type Props = ConnectedProps<typeof connector> & OwnProps;\n\nexport interface State {\n isAdding: boolean;\n newTeamMember?: SelectableValue<OrgUser['userId']> | null;\n}\n\nexport class TeamMembers extends PureComponent<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { isAdding: false, newTeamMember: null };\n }\n\n onSearchQueryChange = (value: string) => {\n this.props.setSearchMemberQuery(value);\n };\n\n onToggleAdding = () => {\n this.setState({ isAdding: !this.state.isAdding });\n };\n\n onUserSelected = (user: SelectableValue<OrgUser['userId']>) => {\n this.setState({ newTeamMember: user });\n };\n\n onAddUserToTeam = async () => {\n this.props.addTeamMember(this.state.newTeamMember!.id);\n this.setState({ newTeamMember: null });\n };\n\n renderLabels(labels: string[]) {\n if (!labels) {\n return <td />;\n }\n\n return (\n <td>\n {labels.map((label) => (\n <TagBadge key={label} label={label} removeIcon={false} count={0} onClick={() => {}} />\n ))}\n </td>\n );\n }\n\n render() {\n const { isAdding } = this.state;\n const { searchMemberQuery, members, syncEnabled, editorsCanAdmin, signedInUser } = this.props;\n const isTeamAdmin = isSignedInUserTeamAdmin({ members, editorsCanAdmin, signedInUser });\n\n return (\n <div>\n <div className=\"page-action-bar\">\n <div className=\"gf-form gf-form--grow\">\n <FilterInput placeholder=\"Search members\" value={searchMemberQuery} onChange={this.onSearchQueryChange} />\n </div>\n <Button className=\"pull-right\" onClick={this.onToggleAdding} disabled={isAdding || !isTeamAdmin}>\n Add member\n </Button>\n </div>\n\n <SlideDown in={isAdding}>\n <div className=\"cta-form\">\n <CloseButton aria-label=\"Close 'Add team member' dialogue\" onClick={this.onToggleAdding} />\n <Label htmlFor=\"user-picker\">Add team member</Label>\n <div className=\"gf-form-inline\">\n <UserPicker inputId=\"user-picker\" onSelected={this.onUserSelected} className=\"min-width-30\" />\n {this.state.newTeamMember && (\n <Button type=\"submit\" onClick={this.onAddUserToTeam}>\n Add to team\n </Button>\n )}\n </div>\n </div>\n </SlideDown>\n\n <div className=\"admin-list-table\">\n <table className=\"filter-table filter-table--hover form-inline\">\n <thead>\n <tr>\n <th />\n <th>Login</th>\n <th>Email</th>\n <th>Name</th>\n <WithFeatureToggle featureToggle={editorsCanAdmin}>\n <th>Permission</th>\n </WithFeatureToggle>\n {syncEnabled && <th />}\n <th style={{ width: '1%' }} />\n </tr>\n </thead>\n <tbody>\n {members &&\n members.map((member) => (\n <TeamMemberRow\n key={member.userId}\n member={member}\n syncEnabled={syncEnabled}\n editorsCanAdmin={editorsCanAdmin}\n signedInUserIsTeamAdmin={isTeamAdmin}\n />\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n }\n}\n\nexport default connector(TeamMembers);\n","import React from 'react';\n\nimport { Permissions } from 'app/core/components/AccessControl';\nimport { contextSrv } from 'app/core/services/context_srv';\n\nimport { AccessControlAction, Team } from '../../types';\n\ntype TeamPermissionsProps = {\n team: Team;\n};\n\n// TeamPermissions component replaces TeamMembers component when the accesscontrol feature flag is set\nconst TeamPermissions = (props: TeamPermissionsProps) => {\n const canSetPermissions = contextSrv.hasPermissionInMetadata(\n AccessControlAction.ActionTeamsPermissionsWrite,\n props.team\n );\n\n return (\n <Permissions\n title=\"Members\"\n addPermissionTitle=\"Add member\"\n buttonLabel=\"Add member\"\n resource=\"teams\"\n resourceId={props.team.id}\n canSetPermissions={canSetPermissions}\n />\n );\n};\n\nexport default TeamPermissions;\n","import React, { FC } from 'react';\nimport { connect, ConnectedProps } from 'react-redux';\n\nimport { Input, Field, Form, Button, FieldSet, VerticalGroup } from '@grafana/ui';\nimport { SharedPreferences } from 'app/core/components/SharedPreferences/SharedPreferences';\nimport { contextSrv } from 'app/core/core';\nimport { AccessControlAction, Team } from 'app/types';\n\nimport { updateTeam } from './state/actions';\n\nconst mapDispatchToProps = {\n updateTeam,\n};\n\nconst connector = connect(null, mapDispatchToProps);\n\ninterface OwnProps {\n team: Team;\n}\nexport type Props = ConnectedProps<typeof connector> & OwnProps;\n\nexport const TeamSettings: FC<Props> = ({ team, updateTeam }) => {\n const canWriteTeamSettings = contextSrv.hasPermissionInMetadata(AccessControlAction.ActionTeamsWrite, team);\n\n return (\n <VerticalGroup>\n <FieldSet label=\"Team settings\">\n <Form\n defaultValues={{ ...team }}\n onSubmit={(formTeam: Team) => {\n updateTeam(formTeam.name, formTeam.email);\n }}\n disabled={!canWriteTeamSettings}\n >\n {({ register }) => (\n <>\n <Field label=\"Name\" disabled={!canWriteTeamSettings}>\n <Input {...register('name', { required: true })} id=\"name-input\" />\n </Field>\n\n <Field\n label=\"Email\"\n description=\"This is optional and is primarily used to set the team profile avatar (via gravatar service).\"\n disabled={!canWriteTeamSettings}\n >\n <Input {...register('email')} placeholder=\"team@email.com\" type=\"email\" id=\"email-input\" />\n </Field>\n <Button type=\"submit\" disabled={!canWriteTeamSettings}>\n Update\n </Button>\n </>\n )}\n </Form>\n </FieldSet>\n <SharedPreferences resourceUri={`teams/${team.id}`} disabled={!canWriteTeamSettings} />\n </VerticalGroup>\n );\n};\n\nexport default connector(TeamSettings);\n","import { includes } from 'lodash';\nimport React, { PureComponent } from 'react';\nimport { connect, ConnectedProps } from 'react-redux';\n\nimport { NavModel } from '@grafana/data';\nimport { featureEnabled } from '@grafana/runtime';\nimport { Themeable2, withTheme2 } from '@grafana/ui';\nimport Page from 'app/core/components/Page/Page';\nimport { UpgradeBox } from 'app/core/components/Upgrade/UpgradeBox';\nimport config from 'app/core/config';\nimport { GrafanaRouteComponentProps } from 'app/core/navigation/types';\nimport { getNavModel } from 'app/core/selectors/navModel';\nimport { contextSrv } from 'app/core/services/context_srv';\nimport { AccessControlAction, StoreState } from 'app/types';\n\nimport TeamGroupSync, { TeamSyncUpgradeContent } from './TeamGroupSync';\nimport TeamMembers from './TeamMembers';\nimport TeamPermissions from './TeamPermissions';\nimport TeamSettings from './TeamSettings';\nimport { loadTeam, loadTeamMembers } from './state/actions';\nimport { getTeamLoadingNav } from './state/navModel';\nimport { getTeam, getTeamMembers, isSignedInUserTeamAdmin } from './state/selectors';\n\ninterface TeamPageRouteParams {\n id: string;\n page: string | null;\n}\n\nexport interface OwnProps extends GrafanaRouteComponentProps<TeamPageRouteParams>, Themeable2 {}\n\ninterface State {\n isSyncEnabled: boolean;\n isLoading: boolean;\n}\n\nenum PageTypes {\n Members = 'members',\n Settings = 'settings',\n GroupSync = 'groupsync',\n}\n\nfunction mapStateToProps(state: StoreState, props: OwnProps) {\n const teamId = parseInt(props.match.params.id, 10);\n const team = getTeam(state.team, teamId);\n let defaultPage = 'members';\n if (contextSrv.accessControlEnabled()) {\n // With RBAC the settings page will always be available\n if (!team || !contextSrv.hasPermissionInMetadata(AccessControlAction.ActionTeamsPermissionsRead, team)) {\n defaultPage = 'settings';\n }\n }\n const pageName = props.match.params.page ?? defaultPage;\n const teamLoadingNav = getTeamLoadingNav(pageName as string);\n const navModel = getNavModel(state.navIndex, `team-${pageName}-${teamId}`, teamLoadingNav);\n const members = getTeamMembers(state.team);\n\n return {\n navModel,\n teamId: teamId,\n pageName: pageName,\n team,\n members,\n editorsCanAdmin: config.editorsCanAdmin, // this makes the feature toggle mockable/controllable from tests,\n signedInUser: contextSrv.user, // this makes the feature toggle mockable/controllable from tests,\n };\n}\n\nconst mapDispatchToProps = {\n loadTeam,\n loadTeamMembers,\n};\n\nconst connector = connect(mapStateToProps, mapDispatchToProps);\n\nexport type Props = OwnProps & ConnectedProps<typeof connector>;\n\nexport class TeamPages extends PureComponent<Props, State> {\n constructor(props: Props) {\n super(props);\n\n this.state = {\n isLoading: false,\n isSyncEnabled: featureEnabled('teamsync'),\n };\n }\n\n async componentDidMount() {\n await this.fetchTeam();\n }\n\n async fetchTeam() {\n const { loadTeam, teamId } = this.props;\n this.setState({ isLoading: true });\n const team = await loadTeam(teamId);\n // With accesscontrol, the TeamPermissions will fetch team members\n if (!contextSrv.accessControlEnabled()) {\n await this.props.loadTeamMembers();\n }\n this.setState({ isLoading: false });\n return team;\n }\n\n getCurrentPage() {\n const pages = ['members', 'settings', 'groupsync'];\n const currentPage = this.props.pageName;\n return includes(pages, currentPage) ? currentPage : pages[0];\n }\n\n textsAreEqual = (text1: string, text2: string) => {\n if (!text1 && !text2) {\n return true;\n }\n\n if (!text1 || !text2) {\n return false;\n }\n\n return text1.toLocaleLowerCase() === text2.toLocaleLowerCase();\n };\n\n hideTabsFromNonTeamAdmin = (navModel: NavModel, isSignedInUserTeamAdmin: boolean) => {\n if (contextSrv.accessControlEnabled()) {\n return navModel;\n }\n\n if (!isSignedInUserTeamAdmin && navModel.main && navModel.main.children) {\n navModel.main.children\n .filter((navItem) => !this.textsAreEqual(navItem.text, PageTypes.Members))\n .map((navItem) => {\n navItem.hideFromTabs = true;\n });\n }\n\n return navModel;\n };\n\n renderPage(isSignedInUserTeamAdmin: boolean): React.ReactNode {\n const { isSyncEnabled } = this.state;\n const { members, team } = this.props;\n const currentPage = this.getCurrentPage();\n\n const canReadTeam = contextSrv.hasAccessInMetadata(\n AccessControlAction.ActionTeamsRead,\n team!,\n isSignedInUserTeamAdmin\n );\n const canReadTeamPermissions = contextSrv.hasAccessInMetadata(\n AccessControlAction.ActionTeamsPermissionsRead,\n team!,\n isSignedInUserTeamAdmin\n );\n const canWriteTeamPermissions = contextSrv.hasAccessInMetadata(\n AccessControlAction.ActionTeamsPermissionsWrite,\n team!,\n isSignedInUserTeamAdmin\n );\n\n switch (currentPage) {\n case PageTypes.Members:\n if (contextSrv.accessControlEnabled()) {\n return <TeamPermissions team={team!} />;\n } else {\n return <TeamMembers syncEnabled={isSyncEnabled} members={members} />;\n }\n case PageTypes.Settings:\n return canReadTeam && <TeamSettings team={team!} />;\n case PageTypes.GroupSync:\n if (isSyncEnabled) {\n if (canReadTeamPermissions) {\n return <TeamGroupSync isReadOnly={!canWriteTeamPermissions} />;\n }\n } else if (config.featureToggles.featureHighlights) {\n return (\n <>\n <UpgradeBox featureName={'team sync'} featureId={'team-sync'} />\n <TeamSyncUpgradeContent />\n </>\n );\n }\n }\n\n return null;\n }\n\n render() {\n const { team, navModel, members, editorsCanAdmin, signedInUser } = this.props;\n const isTeamAdmin = isSignedInUserTeamAdmin({ members, editorsCanAdmin, signedInUser });\n\n return (\n <Page navModel={this.hideTabsFromNonTeamAdmin(navModel, isTeamAdmin)}>\n <Page.Contents isLoading={this.state.isLoading}>\n {team && Object.keys(team).length !== 0 && this.renderPage(isTeamAdmin)}\n </Page.Contents>\n </Page>\n );\n }\n}\n\nexport default connector(withTheme2(TeamPages));\n","import { getBackendSrv } from '@grafana/runtime';\nimport { updateNavIndex } from 'app/core/actions';\nimport { contextSrv } from 'app/core/core';\nimport { accessControlQueryParam } from 'app/core/utils/accessControl';\nimport { AccessControlAction, TeamMember, ThunkResult } from 'app/types';\n\nimport { buildNavModel } from './navModel';\nimport { teamGroupsLoaded, teamLoaded, teamMembersLoaded, teamsLoaded } from './reducers';\n\nexport function loadTeams(): ThunkResult<void> {\n return async (dispatch) => {\n // Early return if the user cannot list teams\n if (!contextSrv.hasPermission(AccessControlAction.ActionTeamsRead)) {\n dispatch(teamsLoaded([]));\n return;\n }\n\n const response = await getBackendSrv().get(\n '/api/teams/search',\n accessControlQueryParam({ perpage: 1000, page: 1 })\n );\n dispatch(teamsLoaded(response.teams));\n };\n}\n\nexport function loadTeam(id: number): ThunkResult<void> {\n return async (dispatch) => {\n const response = await getBackendSrv().get(`/api/teams/${id}`, accessControlQueryParam());\n dispatch(teamLoaded(response));\n dispatch(updateNavIndex(buildNavModel(response)));\n };\n}\n\nexport function loadTeamMembers(): ThunkResult<void> {\n return async (dispatch, getStore) => {\n const team = getStore().team.team;\n const response = await getBackendSrv().get(`/api/teams/${team.id}/members`);\n dispatch(teamMembersLoaded(response));\n };\n}\n\nexport function addTeamMember(id: number): ThunkResult<void> {\n return async (dispatch, getStore) => {\n const team = getStore().team.team;\n await getBackendSrv().post(`/api/teams/${team.id}/members`, { userId: id });\n dispatch(loadTeamMembers());\n };\n}\n\nexport function removeTeamMember(id: number): ThunkResult<void> {\n return async (dispatch, getStore) => {\n const team = getStore().team.team;\n await getBackendSrv().delete(`/api/teams/${team.id}/members/${id}`);\n dispatch(loadTeamMembers());\n };\n}\n\nexport function updateTeam(name: string, email: string): ThunkResult<void> {\n return async (dispatch, getStore) => {\n const team = getStore().team.team;\n await getBackendSrv().put(`/api/teams/${team.id}`, { name, email });\n dispatch(loadTeam(team.id));\n };\n}\n\nexport function loadTeamGroups(): ThunkResult<void> {\n return async (dispatch, getStore) => {\n const team = getStore().team.team;\n const response = await getBackendSrv().get(`/api/teams/${team.id}/groups`);\n dispatch(teamGroupsLoaded(response));\n };\n}\n\nexport function addTeamGroup(groupId: string): ThunkResult<void> {\n return async (dispatch, getStore) => {\n const team = getStore().team.team;\n await getBackendSrv().post(`/api/teams/${team.id}/groups`, { groupId: groupId });\n dispatch(loadTeamGroups());\n };\n}\n\nexport function removeTeamGroup(groupId: string): ThunkResult<void> {\n return async (dispatch, getStore) => {\n const team = getStore().team.team;\n await getBackendSrv().delete(`/api/teams/${team.id}/groups/${encodeURIComponent(groupId)}`);\n dispatch(loadTeamGroups());\n };\n}\n\nexport function deleteTeam(id: number): ThunkResult<void> {\n return async (dispatch) => {\n await getBackendSrv().delete(`/api/teams/${id}`);\n // Update users permissions in case they lost teams.read with the deletion\n await contextSrv.fetchUserPermissions();\n dispatch(loadTeams());\n };\n}\n\nexport function updateTeamMember(member: TeamMember): ThunkResult<void> {\n return async (dispatch) => {\n await getBackendSrv().put(`/api/teams/${member.teamId}/members/${member.userId}`, {\n permission: member.permission,\n });\n dispatch(loadTeamMembers());\n };\n}\n","import { NavModelItem, NavModel } from '@grafana/data';\nimport { featureEnabled } from '@grafana/runtime';\nimport { ProBadge } from 'app/core/components/Upgrade/ProBadge';\nimport config from 'app/core/config';\nimport { contextSrv } from 'app/core/services/context_srv';\nimport { highlightTrial } from 'app/features/admin/utils';\nimport { AccessControlAction, Team, TeamPermissionLevel } from 'app/types';\n\nconst loadingTeam = {\n avatarUrl: 'public/img/user_profile.png',\n id: 1,\n name: 'Loading',\n email: 'loading',\n memberCount: 0,\n permission: TeamPermissionLevel.Member,\n};\n\nexport function buildNavModel(team: Team): NavModelItem {\n const navModel: NavModelItem = {\n img: team.avatarUrl,\n id: 'team-' + team.id,\n subTitle: 'Manage members and settings',\n url: '',\n text: team.name,\n breadcrumbs: [{ title: 'Teams', url: 'org/teams' }],\n children: [\n // With RBAC this tab will always be available (but not always editable)\n // With Legacy it will be hidden by hideTabsFromNonTeamAdmin should the user not be allowed to see it\n {\n active: false,\n icon: 'sliders-v-alt',\n id: `team-settings-${team.id}`,\n text: 'Settings',\n url: `org/teams/edit/${team.id}/settings`,\n },\n ],\n };\n\n // While team is loading we leave the members tab\n // With RBAC the Members tab is available when user has ActionTeamsPermissionsRead for this team\n // With Legacy it will always be present\n if (\n team === loadingTeam ||\n contextSrv.hasPermissionInMetadata(AccessControlAction.ActionTeamsPermissionsRead, team)\n ) {\n navModel.children!.unshift({\n active: false,\n icon: 'users-alt',\n id: `team-members-${team.id}`,\n text: 'Members',\n url: `org/teams/edit/${team.id}/members`,\n });\n }\n\n const teamGroupSync: NavModelItem = {\n active: false,\n icon: 'sync',\n id: `team-groupsync-${team.id}`,\n text: 'External group sync',\n url: `org/teams/edit/${team.id}/groupsync`,\n };\n\n const isLoadingTeam = team === loadingTeam;\n\n if (highlightTrial()) {\n teamGroupSync.tabSuffix = () =>\n ProBadge({ experimentId: isLoadingTeam ? '' : 'feature-highlights-team-sync-badge', eventVariant: 'trial' });\n }\n\n // With both Legacy and RBAC the tab is protected being featureEnabled\n // While team is loading we leave the teamsync tab\n // With RBAC the External Group Sync tab is available when user has ActionTeamsPermissionsRead for this team\n if (featureEnabled('teamsync')) {\n if (isLoadingTeam || contextSrv.hasPermissionInMetadata(AccessControlAction.ActionTeamsPermissionsRead, team)) {\n navModel.children!.push(teamGroupSync);\n }\n } else if (config.featureToggles.featureHighlights) {\n navModel.children!.push({\n ...teamGroupSync,\n tabSuffix: () => ProBadge({ experimentId: isLoadingTeam ? '' : 'feature-highlights-team-sync-badge' }),\n });\n }\n\n return navModel;\n}\n\nexport function getTeamLoadingNav(pageName: string): NavModel {\n const main = buildNavModel(loadingTeam);\n\n let node: NavModelItem;\n\n // find active page\n for (const child of main.children!) {\n if (child.id!.indexOf(pageName) > 0) {\n child.active = true;\n node = child;\n break;\n }\n }\n\n return {\n main: main,\n node: node!,\n };\n}\n","import { User } from 'app/core/services/context_srv';\nimport { Team, TeamsState, TeamState, TeamMember, OrgRole, TeamPermissionLevel } from 'app/types';\n\nexport const getSearchQuery = (state: TeamsState) => state.searchQuery;\nexport const getSearchMemberQuery = (state: TeamState) => state.searchMemberQuery;\nexport const getTeamGroups = (state: TeamState) => state.groups;\nexport const getTeamsCount = (state: TeamsState) => state.teams.length;\nexport const getTeamsSearchPage = (state: TeamsState) => state.searchPage;\n\nexport const getTeam = (state: TeamState, currentTeamId: any): Team | null => {\n if (state.team.id === parseInt(currentTeamId, 10)) {\n return state.team;\n }\n\n return null;\n};\n\nexport const getTeams = (state: TeamsState) => {\n const regex = RegExp(state.searchQuery, 'i');\n\n return state.teams.filter((team) => {\n return regex.test(team.name);\n });\n};\n\nexport const getTeamMembers = (state: TeamState) => {\n const regex = RegExp(state.searchMemberQuery, 'i');\n\n return state.members.filter((member) => {\n return regex.test(member.login) || regex.test(member.email) || regex.test(member.name);\n });\n};\n\nexport interface Config {\n members: TeamMember[];\n editorsCanAdmin: boolean;\n signedInUser: User;\n}\n\nexport const isSignedInUserTeamAdmin = (config: Config): boolean => {\n const { members, signedInUser, editorsCanAdmin } = config;\n const userInMembers = members.find((m) => m.userId === signedInUser.id);\n const permission = userInMembers ? userInMembers.permission : TeamPermissionLevel.Member;\n\n return isPermissionTeamAdmin({ permission, signedInUser, editorsCanAdmin });\n};\n\nexport interface PermissionConfig {\n permission: TeamPermissionLevel;\n editorsCanAdmin: boolean;\n signedInUser: User;\n}\n\nexport const isPermissionTeamAdmin = (config: PermissionConfig): boolean => {\n const { permission, signedInUser, editorsCanAdmin } = config;\n const isAdmin = signedInUser.isGrafanaAdmin || signedInUser.orgRole === OrgRole.Admin;\n const userIsTeamAdmin = permission === TeamPermissionLevel.Admin;\n const isSignedInUserTeamAdmin = isAdmin || userIsTeamAdmin;\n\n return isSignedInUserTeamAdmin || !editorsCanAdmin;\n};\n"],"names":["themes","value","label","id","SharedPreferences","PureComponent","constructor","props","super","async","homeDashboardId","theme","timezone","weekStart","queryHistory","this","state","service","update","window","location","reload","setState","dashboardId","dashboard","folderTitle","title","PreferencesService","resourceUri","dashboards","homeTab","prefs","load","backendSrv","starred","find","d","missing","dashboardIds","length","push","tags","type","uid","uri","url","folderId","folderUid","folderUrl","isStarred","slug","items","render","disabled","styles","getStyles","homeDashboardTooltip","Tooltip","content","Icon","name","Form","onSubmit","onSubmitForm","FieldSet","Field","RadioButtonGroup","options","item","onChange","onThemeChanged","Label","htmlFor","className","labelText","Select","getOptionValue","i","getOptionLabel","getFullDashName","onHomeDashboardChanged","placeholder","inputId","selectors","TimeZonePicker","includeInternal","onTimeZoneChanged","WeekStartPicker","onWeekStartChanged","Button","variant","stylesFactory","css","mapStateToProps","groups","getTeamGroups","team","mapDispatchToProps","loadTeamGroups","addTeamGroup","removeTeamGroup","headerTooltip","connect","TeamGroupSync","isAdding","event","newGroupId","target","preventDefault","group","groupId","componentDidMount","fetchTeamGroups","isNewGroupValid","renderGroup","isReadOnly","style","width","size","onClick","onRemoveGroup","highlightTrial","UpgradeBox","featureId","eventVariant","featureName","text","placement","onToggleAdding","SlideDown","in","CloseButton","onAddGroup","InlineFieldRow","InlineField","Input","onNewGroupIdChanged","marginLeft","TeamSyncUpgradeContent","action","EmptyListCTA","buttonIcon","buttonTitle","proTip","proTipLinkTitle","proTipLink","proTipTarget","buttonDisabled","map","useTheme2","listItems","image","isLight","featureUrl","description","WithFeatureToggle","featureToggle","children","LegacyForms","removeTeamMember","updateTeamMember","connector","TeamMemberRow","member","permission","updatedTeamMember","renderLabels","bind","renderPermissions","onRemoveMember","userId","editorsCanAdmin","signedInUserIsTeamAdmin","teamsPermissionLevels","dp","isSearchable","onPermissionChange","labels","TagBadge","removeIcon","count","syncEnabled","src","avatarUrl","login","email","DeleteButton","onConfirm","addTeamMember","setSearchMemberQuery","searchMemberQuery","getSearchMemberQuery","config","signedInUser","contextSrv","TeamMembers","user","newTeamMember","members","isTeamAdmin","isSignedInUserTeamAdmin","FilterInput","onSearchQueryChange","UserPicker","onSelected","onUserSelected","onAddUserToTeam","canSetPermissions","AccessControlAction","P","addPermissionTitle","buttonLabel","resource","resourceId","updateTeam","canWriteTeamSettings","VerticalGroup","defaultValues","formTeam","register","required","PageTypes","loadTeam","loadTeamMembers","teamId","parseInt","match","params","getTeam","defaultPage","pageName","page","teamLoadingNav","getTeamLoadingNav","navModel","getNavModel","navIndex","getTeamMembers","TeamPages","text1","text2","toLocaleLowerCase","main","filter","navItem","textsAreEqual","Members","hideFromTabs","isLoading","isSyncEnabled","featureEnabled","fetchTeam","getCurrentPage","pages","currentPage","includes","renderPage","canReadTeam","canReadTeamPermissions","canWriteTeamPermissions","Settings","GroupSync","Page","hideTabsFromNonTeamAdmin","Object","keys","withTheme2","loadTeams","dispatch","teamsLoaded","response","getBackendSrv","get","accessControlQueryParam","perpage","teams","teamLoaded","updateNavIndex","buildNavModel","getStore","teamMembersLoaded","post","delete","put","teamGroupsLoaded","encodeURIComponent","deleteTeam","loadingTeam","memberCount","TeamPermissionLevel","img","subTitle","breadcrumbs","active","icon","unshift","teamGroupSync","isLoadingTeam","tabSuffix","ProBadge","experimentId","node","child","indexOf","getSearchQuery","searchQuery","getTeamsCount","getTeamsSearchPage","searchPage","currentTeamId","getTeams","regex","RegExp","test","userInMembers","m","isPermissionTeamAdmin","isAdmin","isGrafanaAdmin","orgRole","OrgRole","userIsTeamAdmin"],"sourceRoot":""}
|