mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
173 lines
4.2 KiB
TypeScript
173 lines
4.2 KiB
TypeScript
import {createStore} from 'reflux';
|
|
|
|
import type {Team} from 'sentry/types';
|
|
import {defined} from 'sentry/utils';
|
|
|
|
import ProjectsStore from './projectsStore';
|
|
import type {CommonStoreDefinition} from './types';
|
|
|
|
type State = {
|
|
cursor: string | null;
|
|
hasMore: boolean | null;
|
|
loadedUserTeams: boolean;
|
|
loading: boolean;
|
|
teams: Team[];
|
|
};
|
|
|
|
interface TeamStoreDefinition extends CommonStoreDefinition<State> {
|
|
getAll(): Team[];
|
|
getById(id: string): Team | null;
|
|
getBySlug(slug: string): Team | null;
|
|
init(): void;
|
|
initialized: boolean;
|
|
loadInitialData(items: Team[], hasMore?: boolean | null, cursor?: string | null): void;
|
|
loadUserTeams(userTeams: Team[]): void;
|
|
onCreateSuccess(team: Team): void;
|
|
onRemoveSuccess(slug: string): void;
|
|
onUpdateSuccess(itemId: string, response: Team): void;
|
|
reset(): void;
|
|
setTeams(teams: Team[], hasMore?: boolean | null, cursor?: string | null): void;
|
|
|
|
state: State;
|
|
}
|
|
|
|
const teamStoreConfig: TeamStoreDefinition = {
|
|
initialized: false,
|
|
state: {
|
|
teams: [],
|
|
loadedUserTeams: false,
|
|
loading: true,
|
|
hasMore: null,
|
|
cursor: null,
|
|
},
|
|
|
|
init() {
|
|
// XXX: Do not use `this.listenTo` in this store. We avoid usage of reflux
|
|
// listeners due to their leaky nature in tests.
|
|
|
|
this.reset();
|
|
},
|
|
|
|
reset() {
|
|
this.state = {
|
|
teams: [],
|
|
loadedUserTeams: false,
|
|
loading: true,
|
|
hasMore: null,
|
|
cursor: null,
|
|
};
|
|
},
|
|
|
|
setTeams(teams, hasMore, cursor) {
|
|
this.initialized = true;
|
|
this.state = {
|
|
teams,
|
|
loadedUserTeams: defined(hasMore) ? !hasMore : this.state.loadedUserTeams,
|
|
loading: false,
|
|
hasMore: hasMore ?? this.state.hasMore,
|
|
cursor: cursor ?? this.state.cursor,
|
|
};
|
|
this.trigger(new Set(teams.map(team => team.id)));
|
|
},
|
|
|
|
loadInitialData(items, hasMore, cursor) {
|
|
const teams = this.updateTeams(items);
|
|
this.setTeams(teams, hasMore, cursor);
|
|
},
|
|
|
|
loadUserTeams(userTeams: Team[]) {
|
|
const teams = this.updateTeams(userTeams);
|
|
|
|
this.state = {
|
|
...this.state,
|
|
loadedUserTeams: true,
|
|
teams,
|
|
};
|
|
|
|
this.trigger(new Set(teams.map(team => team.id)));
|
|
},
|
|
|
|
onUpdateSuccess(itemId, response) {
|
|
if (!response) {
|
|
return;
|
|
}
|
|
|
|
const item = this.getBySlug(itemId);
|
|
|
|
if (!item) {
|
|
this.state = {
|
|
...this.state,
|
|
teams: [...this.state.teams, response],
|
|
};
|
|
|
|
this.trigger(new Set([itemId]));
|
|
return;
|
|
}
|
|
|
|
// Slug was changed
|
|
// Note: This is the proper way to handle slug changes but unfortunately not all of our
|
|
// components use stores correctly. To be safe reload browser :((
|
|
if (response.slug !== itemId) {
|
|
// Replace the team
|
|
const teams = [...this.state.teams.filter(({slug}) => slug !== itemId), response];
|
|
|
|
this.state = {...this.state, teams};
|
|
this.trigger(new Set([response.slug]));
|
|
return;
|
|
}
|
|
|
|
const newTeams = [...this.state.teams];
|
|
const index = newTeams.findIndex(team => team.slug === response.slug);
|
|
newTeams[index] = response;
|
|
|
|
this.state = {...this.state, teams: newTeams};
|
|
this.trigger(new Set([itemId]));
|
|
},
|
|
|
|
onRemoveSuccess(slug: string) {
|
|
const teams = this.state.teams.filter(team => team.slug !== slug);
|
|
this.setTeams(teams);
|
|
ProjectsStore.onDeleteTeam(slug);
|
|
},
|
|
|
|
onCreateSuccess(team: Team) {
|
|
this.loadInitialData([team]);
|
|
},
|
|
|
|
getState() {
|
|
return this.state;
|
|
},
|
|
|
|
getById(id: string) {
|
|
const {teams} = this.state;
|
|
return teams.find(item => item.id.toString() === id.toString()) || null;
|
|
},
|
|
|
|
getBySlug(slug: string) {
|
|
const {teams} = this.state;
|
|
return teams.find(item => item.slug === slug) || null;
|
|
},
|
|
|
|
getAll() {
|
|
return this.state.teams;
|
|
},
|
|
|
|
updateTeams(teams: Team[]) {
|
|
const teamIdMap = this.state.teams.reduce((acc: Record<string, Team>, team: Team) => {
|
|
acc[team.id] = team;
|
|
return acc;
|
|
}, {});
|
|
|
|
// Replace or insert new user teams
|
|
teams.reduce((acc: Record<string, Team>, userTeam: Team) => {
|
|
acc[userTeam.id] = userTeam;
|
|
return acc;
|
|
}, teamIdMap);
|
|
|
|
return Object.values(teamIdMap).sort((a, b) => a.slug.localeCompare(b.slug));
|
|
},
|
|
};
|
|
|
|
const TeamStore = createStore(teamStoreConfig);
|
|
export default TeamStore;
|