123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- import {Component} from 'react';
- import {addLoadingMessage, clearIndicators} from 'sentry/actionCreators/indicator';
- import {ModalRenderProps} from 'sentry/actionCreators/modal';
- import {createSavedSearch} from 'sentry/actionCreators/savedSearches';
- import {Client} from 'sentry/api';
- import Alert from 'sentry/components/alert';
- import {Form, SelectField, TextField} from 'sentry/components/forms';
- import {OnSubmitCallback} from 'sentry/components/forms/type';
- import {t} from 'sentry/locale';
- import {Organization} from 'sentry/types';
- import withApi from 'sentry/utils/withApi';
- import {getSortLabel, IssueSortOptions} from './utils';
- type Props = ModalRenderProps & {
- api: Client;
- organization: Organization;
- query: string;
- sort?: string;
- };
- type State = {
- error: string | null;
- isSaving: boolean;
- };
- const DEFAULT_SORT_OPTIONS = [
- IssueSortOptions.DATE,
- IssueSortOptions.NEW,
- IssueSortOptions.FREQ,
- IssueSortOptions.PRIORITY,
- IssueSortOptions.USER,
- ];
- class CreateSavedSearchModal extends Component<Props, State> {
- state: State = {
- isSaving: false,
- error: null,
- };
- /** Handle "date added" sort not being available for saved searches */
- validateSortOption(sort?: string | null): string {
- if (this.sortOptions().find(option => option === sort)) {
- return sort as string;
- }
- return IssueSortOptions.DATE;
- }
- handleSubmit: OnSubmitCallback = (data, onSubmitSuccess, onSubmitError, event) => {
- const {api, organization} = this.props;
- const sort = this.validateSortOption(data.sort);
- event.preventDefault();
- this.setState({isSaving: true});
- addLoadingMessage(t('Saving Changes'));
- createSavedSearch(api, organization.slug, data.name, data.query, sort)
- .then(_data => {
- this.props.closeModal();
- this.setState({
- error: null,
- isSaving: false,
- });
- clearIndicators();
- onSubmitSuccess(data);
- })
- .catch(err => {
- let error = t('Unable to save your changes.');
- if (err.responseJSON && err.responseJSON.detail) {
- error = err.responseJSON.detail;
- }
- this.setState({
- error,
- isSaving: false,
- });
- clearIndicators();
- onSubmitError(error);
- });
- };
- sortOptions() {
- const {organization} = this.props;
- const options = [...DEFAULT_SORT_OPTIONS];
- if (organization?.features?.includes('issue-list-trend-sort')) {
- options.push(IssueSortOptions.TREND);
- }
- return options;
- }
- render() {
- const {error} = this.state;
- const {Header, Body, closeModal, query, sort} = this.props;
- const sortOptions = this.sortOptions().map(sortOption => ({
- value: sortOption,
- label: getSortLabel(sortOption),
- }));
- const initialData = {
- name: '',
- query,
- sort: this.validateSortOption(sort),
- };
- return (
- <Form
- onSubmit={this.handleSubmit}
- onCancel={closeModal}
- saveOnBlur={false}
- initialData={initialData}
- submitLabel={t('Save')}
- >
- <Header>
- <h4>{t('Save Current Search')}</h4>
- </Header>
- <Body>
- {this.state.error && <Alert type="error">{error}</Alert>}
- <p>{t('All team members will now have access to this search.')}</p>
- <TextField
- key="name"
- name="name"
- label={t('Name')}
- placeholder="e.g. My Search Results"
- inline={false}
- stacked
- flexibleControlStateSize
- required
- />
- <TextField
- key="query"
- name="query"
- label={t('Query')}
- inline={false}
- stacked
- flexibleControlStateSize
- required
- />
- <SelectField
- key="sort"
- name="sort"
- label={t('Sort By')}
- options={sortOptions}
- required
- clearable={false}
- inline={false}
- stacked
- flexibleControlStateSize
- />
- </Body>
- </Form>
- );
- }
- }
- export default withApi(CreateSavedSearchModal);
|