Browse Source

feat(workflow): Save sort with pinned search (#24445)

Scott Cooper 4 years ago
parent
commit
2bf2b2da43

+ 6 - 2
src/sentry/api/endpoints/organization_pinned_searches.py

@@ -4,7 +4,7 @@ from django.db.models import Q
 
 from sentry.api.bases.organization import OrganizationEndpoint, OrganizationPinnedSearchPermission
 from sentry.api.serializers import serialize
-from sentry.models import SavedSearch
+from sentry.models import SavedSearch, SortOptions
 from sentry.models.search_common import SearchType
 
 
@@ -14,6 +14,9 @@ PINNED_SEARCH_NAME = "My Pinned Search"
 class OrganizationSearchSerializer(serializers.Serializer):
     type = serializers.IntegerField(required=True)
     query = serializers.CharField(required=True)
+    sort = serializers.ChoiceField(
+        choices=SortOptions.as_choices(), default=SortOptions.DATE, required=False
+    )
 
     def validate_type(self, value):
         try:
@@ -36,7 +39,7 @@ class OrganizationPinnedSearchEndpoint(OrganizationEndpoint):
                 name=PINNED_SEARCH_NAME,
                 owner=request.user,
                 type=result["type"],
-                values={"query": result["query"]},
+                values={"query": result["query"], "sort": result["sort"]},
             )
             pinned_search = SavedSearch.objects.get(
                 organization=organization, owner=request.user, type=result["type"]
@@ -48,6 +51,7 @@ class OrganizationPinnedSearchEndpoint(OrganizationEndpoint):
                     Q(organization=organization, owner__isnull=True) | Q(is_global=True),
                     type=result["type"],
                     query=result["query"],
+                    sort=result["sort"],
                 )[:1].get()
             except SavedSearch.DoesNotExist:
                 pass

+ 6 - 2
src/sentry/api/endpoints/organization_searches.py

@@ -53,9 +53,13 @@ class OrganizationSearchesEndpoint(OrganizationEndpoint):
             if saved_searches[0].is_pinned:
                 pinned_search = saved_searches[0]
             for saved_search in saved_searches[1:]:
-                # If a search has the same query as the pinned search we
+                # If a search has the same query and sort as the pinned search we
                 # want to use that search as the pinned search
-                if pinned_search and saved_search.query == pinned_search.query:
+                if (
+                    pinned_search
+                    and saved_search.query == pinned_search.query
+                    and saved_search.sort == pinned_search.sort
+                ):
                     saved_search.is_pinned = True
                     results[0] = saved_search
                 else:

+ 4 - 2
src/sentry/static/sentry/app/actionCreators/savedSearches.tsx

@@ -147,18 +147,20 @@ export function pinSearch(
   api: Client,
   orgSlug: string,
   type: SavedSearchType,
-  query: string
+  query: string,
+  sort?: string
 ): Promise<SavedSearch> {
   const url = getPinSearchUrl(orgSlug);
 
   // Optimistically update store
-  SavedSearchesActions.pinSearch(type, query);
+  SavedSearchesActions.pinSearch(type, query, sort);
 
   const promise = api.requestPromise(url, {
     method: 'PUT',
     data: {
       query,
       type,
+      sort,
     },
   });
 

+ 5 - 6
src/sentry/static/sentry/app/components/smartSearchBar/index.tsx

@@ -947,6 +947,7 @@ class SmartSearchBar extends React.Component<Props, State> {
       savedSearchType,
       hasPinnedSearch,
       pinnedSearch,
+      sort,
     } = this.props;
 
     const {router} = this.context;
@@ -978,6 +979,7 @@ class SmartSearchBar extends React.Component<Props, State> {
           query: {
             ...currentQuery,
             query: pinnedSearch.query,
+            sort: pinnedSearch.sort,
           },
         });
       });
@@ -988,7 +990,8 @@ class SmartSearchBar extends React.Component<Props, State> {
       api,
       organization.slug,
       savedSearchType,
-      removeSpace(this.state.query)
+      removeSpace(this.state.query),
+      sort
     );
 
     if (!resp || !resp.id) {
@@ -1097,11 +1100,7 @@ class SmartSearchBar extends React.Component<Props, State> {
     } = this.props;
 
     const pinTooltip = !!pinnedSearch ? t('Unpin this search') : t('Pin this search');
-    const pinIcon = !!pinnedSearch ? (
-      <IconPin isSolid size="xs" />
-    ) : (
-      <IconPin size="xs" />
-    );
+    const pinIcon = <IconPin isSolid={!!pinnedSearch} size="xs" />;
     const hasQuery = !!this.state.query;
 
     const input = (

+ 21 - 17
src/sentry/static/sentry/app/stores/savedSearchesStore.tsx

@@ -15,7 +15,8 @@ type SavedSearchesStoreInterface = {
   get: () => State;
   getFilteredSearches: (type: SavedSearchType, id?: string) => SavedSearch[];
   updateExistingSearch: (id: string, changes: Partial<SavedSearch>) => SavedSearch;
-  findByQuery: (query: string) => SavedSearch | undefined;
+  findByQuery: (query: string, sort: string) => SavedSearch | undefined;
+  onPinSearch: (type: SavedSearchType, query: string, sort: string) => void;
 };
 
 const savedSearchesStoreConfig: Reflux.StoreDefinition & SavedSearchesStoreInterface = {
@@ -114,8 +115,10 @@ const savedSearchesStoreConfig: Reflux.StoreDefinition & SavedSearchesStoreInter
   /**
    * Find saved search by query string
    */
-  findByQuery(query) {
-    return this.state.savedSearches.find(savedSearch => query === savedSearch.query);
+  findByQuery(query, sort) {
+    return this.state.savedSearches.find(
+      savedSearch => query === savedSearch.query && sort === savedSearch.sort
+    );
   },
 
   /**
@@ -174,24 +177,25 @@ const savedSearchesStoreConfig: Reflux.StoreDefinition & SavedSearchesStoreInter
     this.trigger(this.state);
   },
 
-  onPinSearch(type, query) {
-    const existingSearch = this.findByQuery(query);
+  onPinSearch(type, query, sort) {
+    const existingSearch = this.findByQuery(query, sort);
 
     if (existingSearch) {
       this.updateExistingSearch(existingSearch.id, {isPinned: true});
     }
 
-    const newPinnedSearch =
-      (!existingSearch && [
-        {
-          id: null,
-          name: 'My Pinned Search',
-          type,
-          query,
-          isPinned: true,
-        },
-      ]) ||
-      [];
+    const newPinnedSearch = !existingSearch
+      ? [
+          {
+            id: null,
+            name: 'My Pinned Search',
+            type,
+            query,
+            sort,
+            isPinned: true,
+          },
+        ]
+      : [];
 
     this.state = {
       ...this.state,
@@ -207,7 +211,7 @@ const savedSearchesStoreConfig: Reflux.StoreDefinition & SavedSearchesStoreInter
   },
 
   onPinSearchSuccess(resp) {
-    const existingSearch = this.findByQuery(resp.query);
+    const existingSearch = this.findByQuery(resp.query, resp.sort);
 
     if (existingSearch) {
       this.updateExistingSearch(existingSearch.id, resp);

+ 1 - 0
src/sentry/static/sentry/app/views/issueList/filters.tsx

@@ -100,6 +100,7 @@ class IssueListFilters extends React.Component<Props> {
                 onSavedSearchSelect={this.handleSavedSearchSelect}
                 onSavedSearchDelete={onSavedSearchDelete}
                 query={query}
+                sort={sort}
               />
             )}
 

+ 3 - 0
src/sentry/static/sentry/app/views/issueList/header.tsx

@@ -47,6 +47,7 @@ function WrapGuideTabs({children, tabQuery, query, to}: WrapGuideProps) {
 type Props = {
   organization: Organization;
   query: string;
+  sort: string;
   queryCounts: QueryCounts;
   realtimeActive: boolean;
   orgSlug: Organization['slug'];
@@ -61,6 +62,7 @@ type Props = {
 function IssueListHeader({
   organization,
   query,
+  sort,
   queryCount,
   queryCounts,
   realtimeActive,
@@ -165,6 +167,7 @@ function IssueListHeader({
           <SavedSearchTab
             organization={organization}
             query={query}
+            sort={sort}
             savedSearchList={savedSearchList}
             onSavedSearchSelect={onSavedSearchSelect}
             onSavedSearchDelete={onSavedSearchDelete}

+ 1 - 0
src/sentry/static/sentry/app/views/issueList/overview.tsx

@@ -1048,6 +1048,7 @@ class IssueListOverview extends React.Component<Props, State> {
               <IssueListHeader
                 organization={organization}
                 query={query}
+                sort={this.getSort()}
                 queryCount={queryCount}
                 queryCounts={queryCounts}
                 realtimeActive={realtimeActive}

+ 3 - 1
src/sentry/static/sentry/app/views/issueList/savedSearchMenu.tsx

@@ -19,6 +19,7 @@ type Props = {
   savedSearchList: SavedSearch[];
   onSavedSearchSelect: (savedSearch: SavedSearch) => void;
   onSavedSearchDelete: (savedSearch: SavedSearch) => void;
+  sort: string;
   query?: string;
 };
 
@@ -27,6 +28,7 @@ function SavedSearchMenu({
   onSavedSearchDelete,
   onSavedSearchSelect,
   organization,
+  sort,
   query,
 }: Props) {
   if (savedSearchList.length === 0) {
@@ -51,7 +53,7 @@ function SavedSearchMenu({
           key={search.id}
         >
           <StyledMenuItem
-            isActive={search.query === query}
+            isActive={search.query === query && search.sort === sort}
             last={index === savedSearchList.length - 1}
           >
             <MenuItemLink tabIndex={-1} onClick={() => onSavedSearchSelect(search)}>

+ 7 - 2
src/sentry/static/sentry/app/views/issueList/savedSearchSelector.tsx

@@ -14,6 +14,7 @@ type Props = {
   savedSearchList: SavedSearch[];
   onSavedSearchSelect: (savedSearch: SavedSearch) => void;
   onSavedSearchDelete: (savedSearch: SavedSearch) => void;
+  sort: string;
   query?: string;
 };
 
@@ -23,10 +24,13 @@ function SavedSearchSelector({
   onSavedSearchSelect,
   organization,
   query,
+  sort,
 }: Props) {
   function getTitle() {
-    const result = savedSearchList.find(search => query === search.query);
-    return result ? result.name : t('Custom Search');
+    const savedSearch = savedSearchList.find(
+      search => search.query === query && search.sort === sort
+    );
+    return savedSearch ? savedSearch.name : t('Custom Search');
   }
 
   return (
@@ -45,6 +49,7 @@ function SavedSearchSelector({
         onSavedSearchSelect={onSavedSearchSelect}
         onSavedSearchDelete={onSavedSearchDelete}
         query={query}
+        sort={sort}
       />
     </DropdownControl>
   );

Some files were not shown because too many files changed in this diff