Browse Source

ref(ts) Convert MemberListStore to typescript (#19097)

I had to convert items -> state to keep typescript happy. I've also
replaced the `null` state with `undefined` as components lower in the
tree use `User | undefined` and having the same types higher up makes
life easier.
Mark Story 4 years ago
parent
commit
e950d96e32

+ 7 - 7
src/sentry/static/sentry/app/components/assigneeSelector.tsx

@@ -36,7 +36,7 @@ type Props = {
 type State = {
   loading: boolean;
   assignedTo: User;
-  memberList: User[];
+  memberList: User[] | undefined;
 };
 
 const AssigneeSelectorComponent = createReactClass<Props, State>({
@@ -71,7 +71,7 @@ const AssigneeSelectorComponent = createReactClass<Props, State>({
 
   getInitialState() {
     const group = GroupStore.get(this.props.id);
-    const memberList = MemberListStore.loaded ? MemberListStore.getAll() : null;
+    const memberList = MemberListStore.loaded ? MemberListStore.getAll() : undefined;
     const loading = GroupStore.hasStatus(this.props.id, 'assignTo');
 
     return {
@@ -110,13 +110,13 @@ const AssigneeSelectorComponent = createReactClass<Props, State>({
     // XXX(billyvg): this means that once `memberList` is not-null, this component will never update due to `memberList` changes
     // Note: this allows us to show a "loading" state for memberList, but only before `MemberListStore.loadInitialData`
     // is called
-    if (currentMembers === null && nextState.memberList !== currentMembers) {
+    if (currentMembers === undefined && nextState.memberList !== currentMembers) {
       return true;
     }
     return !valueIsEqual(nextState.assignedTo, this.state.assignedTo, true);
   },
 
-  memberList() {
+  memberList(): User[] | undefined {
     return this.props.memberList ? this.props.memberList : this.state.memberList;
   },
 
@@ -255,8 +255,8 @@ const AssigneeSelectorComponent = createReactClass<Props, State>({
               }
               e.stopPropagation();
             }}
-            busy={memberList === null}
-            items={memberList !== null ? this.renderNewDropdownItems() : null}
+            busy={memberList === undefined}
+            items={memberList !== undefined ? this.renderNewDropdownItems() : null}
             alignMenu="right"
             onSelect={this.handleAssign}
             itemSize="small"
@@ -310,7 +310,7 @@ const AssigneeSelectorComponent = createReactClass<Props, State>({
   },
 });
 
-export function putSessionUserFirst(members: User[]): User[] {
+export function putSessionUserFirst(members: User[] | undefined): User[] {
   // If session user is in the filtered list of members, put them at the top
   if (!members) {
     return [];

+ 2 - 2
src/sentry/static/sentry/app/components/selectMembers/index.tsx

@@ -111,14 +111,14 @@ class SelectMembers extends React.Component<Props, State> {
       this.setState({
         memberListLoading: !MemberListStore.isLoaded(),
       });
-    }),
+    }, undefined),
   ];
 
   renderUserBadge = (user: User) => (
     <IdBadge avatarSize={24} user={user} hideEmail useLink={false} />
   );
 
-  createMentionableUser = (user: User) => ({
+  createMentionableUser = (user: User): MentionableUser => ({
     value: user.id,
     label: this.renderUserBadge(user),
     searchKey: getSearchKeyForUser(user),

+ 0 - 55
src/sentry/static/sentry/app/stores/memberListStore.jsx

@@ -1,55 +0,0 @@
-import Reflux from 'reflux';
-
-const MemberListStore = Reflux.createStore({
-  // listenables: MemberActions,
-
-  init() {
-    this.items = [];
-    this.loaded = false;
-  },
-
-  // TODO(dcramer): this should actually come from an action of some sorts
-  loadInitialData(items) {
-    this.items = items;
-    this.loaded = true;
-    this.trigger(this.items, 'initial');
-  },
-
-  isLoaded() {
-    return this.loaded;
-  },
-
-  getById(id) {
-    if (!this.items) {
-      return null;
-    }
-
-    id = '' + id;
-    for (let i = 0; i < this.items.length; i++) {
-      if (this.items[i].id === id) {
-        return this.items[i];
-      }
-    }
-    return null;
-  },
-
-  getByEmail(email) {
-    if (!this.items) {
-      return null;
-    }
-
-    email = email.toLowerCase();
-    for (let i = 0; i < this.items.length; i++) {
-      if (this.items[i].email.toLowerCase() === email) {
-        return this.items[i];
-      }
-    }
-    return null;
-  },
-
-  getAll() {
-    return this.items;
-  },
-});
-
-export default MemberListStore;

+ 72 - 0
src/sentry/static/sentry/app/stores/memberListStore.tsx

@@ -0,0 +1,72 @@
+import Reflux from 'reflux';
+
+import {User} from 'app/types';
+
+type MemberListStoreInterface = {
+  state: User[];
+  loaded: boolean;
+  loadInitialData: (items: User[]) => void;
+  isLoaded: () => boolean;
+  getById: (id: string) => User | undefined;
+  getByEmail: (email: string) => User | undefined;
+  getAll: () => User[];
+};
+
+const memberListStoreConfig: Reflux.StoreDefinition & MemberListStoreInterface = {
+  // listenables: MemberActions,
+
+  loaded: false,
+  state: [],
+
+  init() {
+    this.state = [];
+    this.loaded = false;
+  },
+
+  // TODO(dcramer): this should actually come from an action of some sorts
+  loadInitialData(items: User[]) {
+    this.state = items;
+    this.loaded = true;
+    this.trigger(this.state, 'initial');
+  },
+
+  isLoaded() {
+    return this.loaded;
+  },
+
+  getById(id) {
+    if (!this.state) {
+      return undefined;
+    }
+
+    id = '' + id;
+    for (let i = 0; i < this.state.length; i++) {
+      if (this.state[i].id === id) {
+        return this.state[i];
+      }
+    }
+    return undefined;
+  },
+
+  getByEmail(email) {
+    if (!this.state) {
+      return undefined;
+    }
+
+    email = email.toLowerCase();
+    for (let i = 0; i < this.state.length; i++) {
+      if (this.state[i].email.toLowerCase() === email) {
+        return this.state[i];
+      }
+    }
+    return undefined;
+  },
+
+  getAll() {
+    return this.state;
+  },
+};
+
+type MemberListStore = Reflux.Store & MemberListStoreInterface;
+
+export default Reflux.createStore(memberListStoreConfig) as MemberListStore;

+ 1 - 1
tests/js/spec/components/assigneeSelector.spec.jsx

@@ -76,7 +76,7 @@ describe('AssigneeSelector', function() {
       },
     });
 
-    MemberListStore.items = null;
+    MemberListStore.state = [];
     MemberListStore.loaded = false;
 
     assigneeSelector = mountWithTheme(