Goodbye, GraphQL (#7597)
This commit is contained in:
parent
1fb01dfcdc
commit
a3eeb69277
11 changed files with 41 additions and 1144 deletions
|
|
@ -6,10 +6,10 @@ import {fetchGroupsForMember} from '@actions/remote/groups';
|
|||
import {fetchPostsForUnreadChannels} from '@actions/remote/post';
|
||||
import {type MyPreferencesRequest, fetchMyPreferences} from '@actions/remote/preference';
|
||||
import {fetchRoles} from '@actions/remote/role';
|
||||
import {fetchConfigAndLicense} from '@actions/remote/systems';
|
||||
import {fetchConfigAndLicense, fetchDataRetentionPolicy} from '@actions/remote/systems';
|
||||
import {fetchMyTeams, fetchTeamsChannelsAndUnreadPosts, handleKickFromTeam, type MyTeamsRequest, updateCanJoinTeams} from '@actions/remote/team';
|
||||
import {syncTeamThreads} from '@actions/remote/thread';
|
||||
import {fetchMe, type MyUserRequest, updateAllUsersSince} from '@actions/remote/user';
|
||||
import {fetchMe, type MyUserRequest, updateAllUsersSince, autoUpdateTimezone} from '@actions/remote/user';
|
||||
import {General, Preferences, Screens} from '@constants';
|
||||
import {SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import {PUSH_PROXY_RESPONSE_NOT_AVAILABLE, PUSH_PROXY_RESPONSE_UNKNOWN, PUSH_PROXY_STATUS_NOT_AVAILABLE, PUSH_PROXY_STATUS_UNKNOWN, PUSH_PROXY_STATUS_VERIFIED} from '@constants/push_proxy';
|
||||
|
|
@ -22,7 +22,7 @@ import {getDeviceToken} from '@queries/app/global';
|
|||
import {queryAllChannelsForTeam, queryChannelsById} from '@queries/servers/channel';
|
||||
import {prepareModels, truncateCrtRelatedTables} from '@queries/servers/entry';
|
||||
import {getHasCRTChanged} from '@queries/servers/preference';
|
||||
import {getConfig, getCurrentChannelId, getCurrentTeamId, getPushVerificationStatus, getWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system';
|
||||
import {getConfig, getCurrentChannelId, getCurrentTeamId, getIsDataRetentionEnabled, getPushVerificationStatus, getWebSocketLastDisconnected, setCurrentTeamAndChannelId} from '@queries/servers/system';
|
||||
import {deleteMyTeams, getAvailableTeamIds, getTeamChannelHistory, queryMyTeams, queryMyTeamsByIds, queryTeamsById} from '@queries/servers/team';
|
||||
import NavigationStore from '@store/navigation_store';
|
||||
import {isDMorGM, sortChannelsByDisplayName} from '@utils/channel';
|
||||
|
|
@ -63,13 +63,37 @@ export type EntryResponse = {
|
|||
const FETCH_MISSING_DM_TIMEOUT = 2500;
|
||||
export const FETCH_UNREADS_TIMEOUT = 2500;
|
||||
|
||||
export const getRemoveTeamIds = async (database: Database, teamData: MyTeamsRequest) => {
|
||||
export const entry = async (serverUrl: string, teamId?: string, channelId?: string, since = 0): Promise<EntryResponse> => {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const result = entryRest(serverUrl, teamId, channelId, since);
|
||||
|
||||
// Fetch data retention policies
|
||||
const isDataRetentionEnabled = await getIsDataRetentionEnabled(database);
|
||||
if (isDataRetentionEnabled) {
|
||||
fetchDataRetentionPolicy(serverUrl);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export async function deferredAppEntryActions(
|
||||
serverUrl: string, since: number, currentUserId: string, currentUserLocale: string, preferences: PreferenceType[] | undefined,
|
||||
config: ClientConfig, license: ClientLicense | undefined, teamData: MyTeamsRequest, chData: MyChannelsRequest | undefined,
|
||||
initialTeamId?: string, initialChannelId?: string) {
|
||||
const result = restDeferredAppEntryActions(serverUrl, since, currentUserId, currentUserLocale, preferences, config, license, teamData, chData, initialTeamId, initialChannelId);
|
||||
|
||||
autoUpdateTimezone(serverUrl);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const getRemoveTeamIds = async (database: Database, teamData: MyTeamsRequest) => {
|
||||
const myTeams = await queryMyTeams(database).fetch();
|
||||
const joinedTeams = new Set(teamData.memberships?.filter((m) => m.delete_at === 0).map((m) => m.team_id));
|
||||
return myTeams.filter((m) => !joinedTeams.has(m.id)).map((m) => m.id);
|
||||
};
|
||||
|
||||
export const teamsToRemove = async (serverUrl: string, removeTeamIds?: string[]) => {
|
||||
const teamsToRemove = async (serverUrl: string, removeTeamIds?: string[]) => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return [];
|
||||
|
|
@ -90,7 +114,7 @@ export const teamsToRemove = async (serverUrl: string, removeTeamIds?: string[])
|
|||
return [];
|
||||
};
|
||||
|
||||
export const entryRest = async (serverUrl: string, teamId?: string, channelId?: string, since = 0): Promise<EntryResponse> => {
|
||||
const entryRest = async (serverUrl: string, teamId?: string, channelId?: string, since = 0): Promise<EntryResponse> => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
|
|
@ -137,7 +161,7 @@ export const entryRest = async (serverUrl: string, teamId?: string, channelId?:
|
|||
return {models: models.flat(), initialChannelId, initialTeamId, prefData, teamData, chData, meData};
|
||||
};
|
||||
|
||||
export const fetchAppEntryData = async (serverUrl: string, sinceArg: number, initialTeamId = ''): Promise<AppEntryData | AppEntryError> => {
|
||||
const fetchAppEntryData = async (serverUrl: string, sinceArg: number, initialTeamId = ''): Promise<AppEntryData | AppEntryError> => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (!database) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
|
|
@ -244,7 +268,7 @@ export const fetchAppEntryData = async (serverUrl: string, sinceArg: number, ini
|
|||
return data;
|
||||
};
|
||||
|
||||
export const fetchAlternateTeamData = async (
|
||||
const fetchAlternateTeamData = async (
|
||||
serverUrl: string, availableTeamIds: string[], removeTeamIds: string[],
|
||||
includeDeleted = true, since = 0, fetchOnly = false, isCRTEnabled?: boolean) => {
|
||||
let initialTeamId = '';
|
||||
|
|
@ -269,7 +293,7 @@ export const fetchAlternateTeamData = async (
|
|||
return {initialTeamId, removeTeamIds};
|
||||
};
|
||||
|
||||
export async function entryInitialChannelId(database: Database, requestedChannelId = '', requestedTeamId = '', initialTeamId: string, locale: string, channels?: Channel[], memberships?: ChannelMember[]) {
|
||||
async function entryInitialChannelId(database: Database, requestedChannelId = '', requestedTeamId = '', initialTeamId: string, locale: string, channels?: Channel[], memberships?: ChannelMember[]) {
|
||||
const membershipIds = new Set(memberships?.map((m) => m.channel_id));
|
||||
const requestedChannel = channels?.find((c) => (c.id === requestedChannelId) && membershipIds.has(c.id));
|
||||
|
||||
|
|
@ -307,7 +331,7 @@ export async function entryInitialChannelId(database: Database, requestedChannel
|
|||
return myFirstTeamChannel?.id || '';
|
||||
}
|
||||
|
||||
export async function restDeferredAppEntryActions(
|
||||
async function restDeferredAppEntryActions(
|
||||
serverUrl: string, since: number, currentUserId: string, currentUserLocale: string, preferences: PreferenceType[] | undefined,
|
||||
config: ClientConfig, license: ClientLicense | undefined, teamData: MyTeamsRequest, chData: MyChannelsRequest | undefined,
|
||||
initialTeamId?: string, initialChannelId?: string) {
|
||||
|
|
|
|||
|
|
@ -1,310 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {storeConfigAndLicense} from '@actions/local/systems';
|
||||
import {fetchGroupsForMember} from '@actions/remote/groups';
|
||||
import {fetchPostsForUnreadChannels} from '@actions/remote/post';
|
||||
import {fetchDataRetentionPolicy} from '@actions/remote/systems';
|
||||
import {type MyTeamsRequest, updateCanJoinTeams} from '@actions/remote/team';
|
||||
import {syncTeamThreads} from '@actions/remote/thread';
|
||||
import {autoUpdateTimezone, fetchProfilesInGroupChannels, updateAllUsersSince} from '@actions/remote/user';
|
||||
import {gqlEntry, gqlEntryChannels, gqlOtherChannels} from '@client/graphQL/entry';
|
||||
import {General, Preferences} from '@constants';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {getPreferenceValue} from '@helpers/api/preference';
|
||||
import {selectDefaultTeam} from '@helpers/api/team';
|
||||
import {queryAllChannels, queryAllChannelsForTeam} from '@queries/servers/channel';
|
||||
import {prepareModels, truncateCrtRelatedTables} from '@queries/servers/entry';
|
||||
import {getHasCRTChanged} from '@queries/servers/preference';
|
||||
import {getConfig, getIsDataRetentionEnabled} from '@queries/servers/system';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {filterAndTransformRoles, getMemberChannelsFromGQLQuery, getMemberTeamsFromGQLQuery, gqlToClientChannelMembership, gqlToClientPreference, gqlToClientSidebarCategory, gqlToClientTeamMembership, gqlToClientUser} from '@utils/graphql';
|
||||
import {logDebug} from '@utils/log';
|
||||
import {processIsCRTEnabled} from '@utils/thread';
|
||||
|
||||
import {teamsToRemove, FETCH_UNREADS_TIMEOUT, entryRest, type EntryResponse, entryInitialChannelId, restDeferredAppEntryActions, getRemoveTeamIds} from './common';
|
||||
|
||||
import type {MyChannelsRequest} from '@actions/remote/channel';
|
||||
import type {Database} from '@nozbe/watermelondb';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
|
||||
const FETCH_MISSING_GM_TIMEOUT = 2500;
|
||||
|
||||
export async function deferredAppEntryGraphQLActions(
|
||||
serverUrl: string,
|
||||
since: number,
|
||||
currentUserId: string,
|
||||
teamData: MyTeamsRequest,
|
||||
chData: MyChannelsRequest | undefined,
|
||||
preferences: PreferenceType[] | undefined,
|
||||
config: ClientConfig,
|
||||
initialTeamId?: string,
|
||||
initialChannelId?: string,
|
||||
) {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
setTimeout(() => {
|
||||
if (chData?.channels?.length && chData.memberships?.length) {
|
||||
// defer fetching posts for unread channels on initial team
|
||||
fetchPostsForUnreadChannels(serverUrl, chData.channels, chData.memberships, initialChannelId);
|
||||
}
|
||||
}, FETCH_UNREADS_TIMEOUT);
|
||||
|
||||
if (preferences && processIsCRTEnabled(preferences, config.CollapsedThreads, config.FeatureFlagCollapsedThreads, config.Version)) {
|
||||
if (initialTeamId) {
|
||||
await syncTeamThreads(serverUrl, initialTeamId);
|
||||
}
|
||||
|
||||
if (teamData.teams?.length) {
|
||||
for await (const team of teamData.teams) {
|
||||
if (team.id !== initialTeamId) {
|
||||
// need to await here since GM/DM threads in different teams overlap
|
||||
await syncTeamThreads(serverUrl, team.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (initialTeamId) {
|
||||
const result = await getChannelData(serverUrl, initialTeamId, currentUserId, true);
|
||||
if ('error' in result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const removeChannels = await getRemoveChannels(database, result.chData, initialTeamId, false);
|
||||
|
||||
const modelPromises = await prepareModels({operator, removeChannels, chData: result.chData}, true);
|
||||
|
||||
const roles = filterAndTransformRoles(result.roles);
|
||||
if (roles.length) {
|
||||
modelPromises.push(operator.handleRole({roles, prepareRecordsOnly: true}));
|
||||
}
|
||||
const models = (await Promise.all(modelPromises)).flat();
|
||||
operator.batchRecords(models, 'deferredAppEntryActions');
|
||||
|
||||
setTimeout(() => {
|
||||
if (result.chData?.channels?.length && result.chData.memberships?.length) {
|
||||
// defer fetching posts for unread channels on other teams
|
||||
fetchPostsForUnreadChannels(serverUrl, result.chData.channels, result.chData.memberships, initialChannelId);
|
||||
}
|
||||
}, FETCH_UNREADS_TIMEOUT);
|
||||
}
|
||||
|
||||
// Fetch groups for current user
|
||||
fetchGroupsForMember(serverUrl, currentUserId);
|
||||
|
||||
updateCanJoinTeams(serverUrl);
|
||||
updateAllUsersSince(serverUrl, since);
|
||||
|
||||
// defer sidebar GM profiles
|
||||
setTimeout(async () => {
|
||||
const gmIds = chData?.channels?.reduce<Set<string>>((acc, v) => {
|
||||
if (v?.type === General.GM_CHANNEL) {
|
||||
acc.add(v.id);
|
||||
}
|
||||
return acc;
|
||||
}, new Set<string>());
|
||||
if (gmIds?.size) {
|
||||
fetchProfilesInGroupChannels(serverUrl, Array.from(gmIds));
|
||||
}
|
||||
}, FETCH_MISSING_GM_TIMEOUT);
|
||||
|
||||
return {error: undefined};
|
||||
}
|
||||
|
||||
const getRemoveChannels = async (database: Database, chData: MyChannelsRequest | undefined, initialTeamId: string, singleTeam: boolean) => {
|
||||
const removeChannels: ChannelModel[] = [];
|
||||
if (chData?.channels) {
|
||||
const fetchedChannelIds = chData.channels?.map((channel) => channel.id);
|
||||
|
||||
const query = singleTeam ? queryAllChannelsForTeam(database, initialTeamId) : queryAllChannels(database);
|
||||
const channels = await query.fetch();
|
||||
|
||||
for (const channel of channels) {
|
||||
const excludeCondition = singleTeam ? true : channel.teamId !== initialTeamId && channel.teamId !== '';
|
||||
if (excludeCondition && !fetchedChannelIds?.includes(channel.id)) {
|
||||
removeChannels.push(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return removeChannels;
|
||||
};
|
||||
|
||||
const getChannelData = async (serverUrl: string, initialTeamId: string, userId: string, exclude: boolean): Promise<{chData: MyChannelsRequest; roles: Array<Partial<GQLRole>|undefined>} | {error: unknown}> => {
|
||||
let response;
|
||||
try {
|
||||
const request = exclude ? gqlOtherChannels : gqlEntryChannels;
|
||||
response = await request(serverUrl, initialTeamId);
|
||||
} catch (error) {
|
||||
return {error: getFullErrorMessage(error)};
|
||||
}
|
||||
|
||||
if ('error' in response) {
|
||||
return {error: response.error};
|
||||
}
|
||||
|
||||
if ('errors' in response && response.errors?.length) {
|
||||
return {error: response.errors[0].message};
|
||||
}
|
||||
|
||||
const channelsFetchedData = response.data;
|
||||
|
||||
const chData = {
|
||||
channels: getMemberChannelsFromGQLQuery(channelsFetchedData),
|
||||
memberships: channelsFetchedData.channelMembers?.map((m) => gqlToClientChannelMembership(m, userId)),
|
||||
categories: channelsFetchedData.sidebarCategories?.map((c) => gqlToClientSidebarCategory(c, '')),
|
||||
};
|
||||
const roles = channelsFetchedData.channelMembers?.map((m) => m.roles).flat() || [];
|
||||
|
||||
return {chData, roles};
|
||||
};
|
||||
|
||||
export const entryGQL = async (serverUrl: string, currentTeamId?: string, currentChannelId?: string): Promise<EntryResponse> => {
|
||||
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
|
||||
if (!operator) {
|
||||
return {error: `${serverUrl} database not found`};
|
||||
}
|
||||
const {database} = operator;
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await gqlEntry(serverUrl);
|
||||
} catch (error) {
|
||||
return {error: getFullErrorMessage(error)};
|
||||
}
|
||||
|
||||
if ('error' in response) {
|
||||
return {error: response.error};
|
||||
}
|
||||
|
||||
if ('errors' in response && response.errors?.length) {
|
||||
return {error: response.errors[0].message};
|
||||
}
|
||||
|
||||
const fetchedData = response.data;
|
||||
|
||||
const config = fetchedData.config || {} as ClientConfig;
|
||||
const license = fetchedData.license || {} as ClientLicense;
|
||||
await storeConfigAndLicense(serverUrl, config, license);
|
||||
|
||||
const meData = {
|
||||
user: gqlToClientUser(fetchedData.user!),
|
||||
};
|
||||
|
||||
const allTeams = getMemberTeamsFromGQLQuery(fetchedData);
|
||||
const allTeamMemberships = fetchedData.teamMembers.map((m) => gqlToClientTeamMembership(m, meData.user.id));
|
||||
|
||||
const [nonArchivedTeams, archivedTeamIds] = allTeams.reduce((acc, t) => {
|
||||
if (t.delete_at) {
|
||||
acc[1].add(t.id);
|
||||
return acc;
|
||||
}
|
||||
return [[...acc[0], t], acc[1]];
|
||||
}, [[], new Set<string>()]);
|
||||
|
||||
const nonArchivedTeamMemberships = allTeamMemberships.filter((m) => !archivedTeamIds.has(m.team_id));
|
||||
|
||||
const teamData = {
|
||||
teams: nonArchivedTeams,
|
||||
memberships: nonArchivedTeamMemberships,
|
||||
};
|
||||
|
||||
const prefData = {
|
||||
preferences: fetchedData.user?.preferences?.map(gqlToClientPreference),
|
||||
};
|
||||
|
||||
if (prefData.preferences) {
|
||||
const crtToggled = await getHasCRTChanged(database, prefData.preferences);
|
||||
if (crtToggled) {
|
||||
const {error} = await truncateCrtRelatedTables(serverUrl);
|
||||
if (error) {
|
||||
return {error: `Resetting CRT on ${serverUrl} failed`};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let initialTeamId = currentTeamId;
|
||||
if (!teamData.teams.length) {
|
||||
initialTeamId = '';
|
||||
} else if (!initialTeamId || !teamData.teams.find((t) => t.id === currentTeamId && t.delete_at === 0)) {
|
||||
const teamOrderPreference = getPreferenceValue<string>(prefData.preferences || [], Preferences.CATEGORIES.TEAMS_ORDER, '', '');
|
||||
initialTeamId = selectDefaultTeam(teamData.teams, meData.user.locale, teamOrderPreference, config.ExperimentalPrimaryTeam)?.id || '';
|
||||
}
|
||||
const gqlRoles = [
|
||||
...fetchedData.user?.roles || [],
|
||||
...fetchedData.teamMembers?.map((m) => m.roles).flat() || [],
|
||||
];
|
||||
|
||||
let chData;
|
||||
if (initialTeamId) {
|
||||
const result = await getChannelData(serverUrl, initialTeamId, meData.user.id, false);
|
||||
if ('error' in result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
chData = result.chData;
|
||||
gqlRoles.push(...result.roles);
|
||||
}
|
||||
|
||||
const roles = filterAndTransformRoles(gqlRoles);
|
||||
|
||||
const initialChannelId = await entryInitialChannelId(database, currentChannelId, currentTeamId, initialTeamId, meData.user.id, chData?.channels, chData?.memberships);
|
||||
const removeChannels = await getRemoveChannels(database, chData, initialTeamId, true);
|
||||
const removeTeamIds = await getRemoveTeamIds(database, teamData);
|
||||
const removeTeams = await teamsToRemove(serverUrl, removeTeamIds);
|
||||
|
||||
const modelPromises = await prepareModels({operator, initialTeamId, removeTeams, removeChannels, teamData, chData, prefData, meData}, true);
|
||||
if (roles.length) {
|
||||
modelPromises.push(operator.handleRole({roles, prepareRecordsOnly: true}));
|
||||
}
|
||||
const models = (await Promise.all(modelPromises)).flat();
|
||||
return {models, initialTeamId, initialChannelId, prefData, teamData, chData, meData};
|
||||
};
|
||||
|
||||
export const entry = async (serverUrl: string, teamId?: string, channelId?: string, since = 0): Promise<EntryResponse> => {
|
||||
const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const config = await getConfig(database);
|
||||
let result;
|
||||
if (config?.FeatureFlagGraphQL === 'true') {
|
||||
result = await entryGQL(serverUrl, teamId, channelId);
|
||||
if ('error' in result) {
|
||||
logDebug('Error using GraphQL, trying REST', result.error);
|
||||
result = entryRest(serverUrl, teamId, channelId, since);
|
||||
}
|
||||
} else {
|
||||
result = entryRest(serverUrl, teamId, channelId, since);
|
||||
}
|
||||
|
||||
// Fetch data retention policies
|
||||
const isDataRetentionEnabled = await getIsDataRetentionEnabled(database);
|
||||
if (isDataRetentionEnabled) {
|
||||
fetchDataRetentionPolicy(serverUrl);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export async function deferredAppEntryActions(
|
||||
serverUrl: string, since: number, currentUserId: string, currentUserLocale: string, preferences: PreferenceType[] | undefined,
|
||||
config: ClientConfig, license: ClientLicense | undefined, teamData: MyTeamsRequest, chData: MyChannelsRequest | undefined,
|
||||
initialTeamId?: string, initialChannelId?: string) {
|
||||
let result;
|
||||
if (config?.FeatureFlagGraphQL === 'true') {
|
||||
result = await deferredAppEntryGraphQLActions(serverUrl, since, currentUserId, teamData, chData, preferences, config, initialTeamId, initialChannelId);
|
||||
if (result.error) {
|
||||
logDebug('Error using GraphQL, trying REST', result.error);
|
||||
result = restDeferredAppEntryActions(serverUrl, since, currentUserId, currentUserLocale, preferences, config, license, teamData, chData, initialTeamId, initialChannelId);
|
||||
}
|
||||
} else {
|
||||
result = restDeferredAppEntryActions(serverUrl, since, currentUserId, currentUserLocale, preferences, config, license, teamData, chData, initialTeamId, initialChannelId);
|
||||
}
|
||||
|
||||
autoUpdateTimezone(serverUrl);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -4,8 +4,7 @@
|
|||
import {markChannelAsViewed} from '@actions/local/channel';
|
||||
import {dataRetentionCleanup} from '@actions/local/systems';
|
||||
import {markChannelAsRead} from '@actions/remote/channel';
|
||||
import {handleEntryAfterLoadNavigation, registerDeviceToken} from '@actions/remote/entry/common';
|
||||
import {deferredAppEntryActions, entry} from '@actions/remote/entry/gql_common';
|
||||
import {deferredAppEntryActions, entry, handleEntryAfterLoadNavigation, registerDeviceToken} from '@actions/remote/entry/common';
|
||||
import {fetchPostsForChannel, fetchPostThread} from '@actions/remote/post';
|
||||
import {openAllUnreadChannels} from '@actions/remote/preference';
|
||||
import {autoUpdateTimezone} from '@actions/remote/user';
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
export const QUERY_ENTRY = 'gql_m_entry';
|
||||
export const QUERY_CHANNELS = 'gql_m_channels';
|
||||
export const QUERY_CHANNELS_NEXT = 'gql_m_channels_next';
|
||||
export const QUERY_ALL_CHANNELS = 'gql_m_all_channels';
|
||||
export const QUERY_ALL_CHANNELS_NEXT = 'gql_m_all_channels_next';
|
||||
|
||||
export default {
|
||||
QUERY_ENTRY,
|
||||
QUERY_CHANNELS,
|
||||
QUERY_CHANNELS_NEXT,
|
||||
QUERY_ALL_CHANNELS,
|
||||
QUERY_ALL_CHANNELS_NEXT,
|
||||
};
|
||||
|
|
@ -1,392 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {MEMBERS_PER_PAGE} from '@constants/graphql';
|
||||
import NetworkManager from '@managers/network_manager';
|
||||
import {getFullErrorMessage} from '@utils/errors';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import QueryNames from './constants';
|
||||
|
||||
const doGQLQuery = async (serverUrl: string, query: string, variables: {[name: string]: any}, operationName: string) => {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const response = await client.doFetch('/api/v5/graphql', {method: 'post', body: {query, variables, operationName}}) as GQLResponse;
|
||||
return response;
|
||||
} catch (error) {
|
||||
logDebug('error on doGQLQuery', getFullErrorMessage(error));
|
||||
return {error};
|
||||
}
|
||||
};
|
||||
|
||||
export const gqlEntry = async (serverUrl: string) => {
|
||||
return doGQLQuery(serverUrl, entryQuery, {}, QueryNames.QUERY_ENTRY);
|
||||
};
|
||||
|
||||
export const gqlEntryChannels = async (serverUrl: string, teamId: string) => {
|
||||
const variables = {
|
||||
teamId,
|
||||
exclude: false,
|
||||
perPage: MEMBERS_PER_PAGE,
|
||||
};
|
||||
const response = await doGQLQuery(serverUrl, channelsQuery, variables, QueryNames.QUERY_CHANNELS);
|
||||
if ('error' in response || response.errors) {
|
||||
return response;
|
||||
}
|
||||
|
||||
let members = response.data.channelMembers;
|
||||
|
||||
while (members?.length === MEMBERS_PER_PAGE) {
|
||||
let pageResponse;
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
pageResponse = await gqlEntryChannelsNextPage(serverUrl, teamId, members[members.length - 1].cursor!, false);
|
||||
} catch {
|
||||
break;
|
||||
}
|
||||
|
||||
if ('error' in pageResponse) {
|
||||
break;
|
||||
}
|
||||
|
||||
members = pageResponse.data.channelMembers!;
|
||||
response.data.channelMembers?.push(...members);
|
||||
}
|
||||
|
||||
return response;
|
||||
};
|
||||
const gqlEntryChannelsNextPage = async (serverUrl: string, teamId: string, cursor: string, exclude: boolean) => {
|
||||
const variables = {
|
||||
teamId,
|
||||
exclude,
|
||||
perPage: MEMBERS_PER_PAGE,
|
||||
cursor,
|
||||
};
|
||||
return doGQLQuery(serverUrl, nextPageChannelsQuery, variables, QueryNames.QUERY_CHANNELS_NEXT);
|
||||
};
|
||||
|
||||
export const gqlOtherChannels = async (serverUrl: string, teamId: string) => {
|
||||
const variables = {
|
||||
teamId,
|
||||
exclude: true,
|
||||
perPage: MEMBERS_PER_PAGE,
|
||||
};
|
||||
const response = await doGQLQuery(serverUrl, channelsQuery, variables, QueryNames.QUERY_CHANNELS);
|
||||
if ('error' in response || response.errors) {
|
||||
return response;
|
||||
}
|
||||
|
||||
let members = response.data.channelMembers;
|
||||
|
||||
while (members?.length === MEMBERS_PER_PAGE) {
|
||||
let pageResponse;
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
pageResponse = await gqlEntryChannelsNextPage(serverUrl, teamId, members[members.length - 1].cursor!, true);
|
||||
} catch {
|
||||
break;
|
||||
}
|
||||
|
||||
if ('error' in pageResponse || 'errors' in pageResponse) {
|
||||
break;
|
||||
}
|
||||
|
||||
members = pageResponse.data.channelMembers!;
|
||||
response.data.channelMembers?.push(...members);
|
||||
}
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
export const gqlAllChannels = async (serverUrl: string) => {
|
||||
const variables = {
|
||||
perPage: MEMBERS_PER_PAGE,
|
||||
};
|
||||
const response = await doGQLQuery(serverUrl, allChannelsQuery, variables, QueryNames.QUERY_ALL_CHANNELS);
|
||||
if ('error' in response || response.errors) {
|
||||
return response;
|
||||
}
|
||||
|
||||
let members = response.data.channelMembers;
|
||||
|
||||
while (members?.length === MEMBERS_PER_PAGE) {
|
||||
let pageResponse;
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
pageResponse = await gqlAllChannelsNextPage(serverUrl, members[members.length - 1].cursor!);
|
||||
} catch {
|
||||
break;
|
||||
}
|
||||
|
||||
if ('error' in pageResponse || 'errors' in pageResponse) {
|
||||
break;
|
||||
}
|
||||
|
||||
members = pageResponse.data.channelMembers!;
|
||||
response.data.channelMembers?.push(...members);
|
||||
}
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
const gqlAllChannelsNextPage = async (serverUrl: string, cursor: string) => {
|
||||
const variables = {
|
||||
perPage: MEMBERS_PER_PAGE,
|
||||
cursor,
|
||||
};
|
||||
return doGQLQuery(serverUrl, nextPageAllChannelsQuery, variables, QueryNames.QUERY_ALL_CHANNELS_NEXT);
|
||||
};
|
||||
|
||||
const entryQuery = `
|
||||
query ${QueryNames.QUERY_ENTRY} {
|
||||
config
|
||||
license
|
||||
user(id:"me") {
|
||||
id
|
||||
createAt
|
||||
updateAt
|
||||
deleteAt
|
||||
username
|
||||
authService
|
||||
email
|
||||
emailVerified
|
||||
nickname
|
||||
firstName
|
||||
lastName
|
||||
position
|
||||
roles {
|
||||
id
|
||||
name
|
||||
permissions
|
||||
}
|
||||
locale
|
||||
notifyProps
|
||||
props
|
||||
timezone
|
||||
isBot
|
||||
lastPictureUpdate
|
||||
remoteId
|
||||
status {
|
||||
status
|
||||
}
|
||||
botDescription
|
||||
botLastIconUpdate
|
||||
preferences{
|
||||
category
|
||||
name
|
||||
value
|
||||
userId
|
||||
}
|
||||
sessions {
|
||||
createAt
|
||||
expiresAt
|
||||
}
|
||||
termsOfServiceId
|
||||
termsOfServiceCreateAt
|
||||
}
|
||||
teamMembers(userId:"me") {
|
||||
deleteAt
|
||||
schemeAdmin
|
||||
roles {
|
||||
id
|
||||
name
|
||||
permissions
|
||||
}
|
||||
team {
|
||||
id
|
||||
description
|
||||
displayName
|
||||
name
|
||||
type
|
||||
allowedDomains
|
||||
lastTeamIconUpdate
|
||||
groupConstrained
|
||||
allowOpenInvite
|
||||
createAt
|
||||
updateAt
|
||||
deleteAt
|
||||
schemeId
|
||||
policyId
|
||||
cloudLimitsArchived
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const channelsQuery = `
|
||||
query ${QueryNames.QUERY_CHANNELS}($teamId: String!, $perPage: Int!, $exclude: Boolean!) {
|
||||
channelMembers(userId:"me", first:$perPage, teamId:$teamId, excludeTeam:$exclude) {
|
||||
cursor
|
||||
msgCount
|
||||
msgCountRoot
|
||||
mentionCount
|
||||
mentionCountRoot
|
||||
schemeAdmin
|
||||
lastViewedAt
|
||||
notifyProps
|
||||
roles {
|
||||
id
|
||||
name
|
||||
permissions
|
||||
}
|
||||
channel {
|
||||
id
|
||||
header
|
||||
purpose
|
||||
type
|
||||
createAt
|
||||
updateAt
|
||||
creatorId
|
||||
deleteAt
|
||||
displayName
|
||||
prettyDisplayName
|
||||
groupConstrained
|
||||
name
|
||||
shared
|
||||
lastPostAt
|
||||
totalMsgCount
|
||||
totalMsgCountRoot
|
||||
lastRootPostAt
|
||||
team {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
sidebarCategories(userId:"me", teamId:$teamId, excludeTeam:$exclude) {
|
||||
displayName
|
||||
id
|
||||
sortOrder
|
||||
sorting
|
||||
type
|
||||
muted
|
||||
collapsed
|
||||
channelIds
|
||||
teamId
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const nextPageChannelsQuery = `
|
||||
query ${QueryNames.QUERY_CHANNELS_NEXT}($teamId: String!, $perPage: Int!, $exclude: Boolean!, $cursor: String!) {
|
||||
channelMembers(userId:"me", first:$perPage, after:$cursor, teamId:$teamId, excludeTeam:$exclude) {
|
||||
cursor
|
||||
msgCount
|
||||
msgCountRoot
|
||||
mentionCount
|
||||
mentionCountRoot
|
||||
schemeAdmin
|
||||
lastViewedAt
|
||||
notifyProps
|
||||
roles {
|
||||
id
|
||||
name
|
||||
permissions
|
||||
}
|
||||
channel {
|
||||
id
|
||||
header
|
||||
purpose
|
||||
type
|
||||
createAt
|
||||
updateAt
|
||||
creatorId
|
||||
deleteAt
|
||||
displayName
|
||||
prettyDisplayName
|
||||
groupConstrained
|
||||
name
|
||||
shared
|
||||
lastPostAt
|
||||
totalMsgCount
|
||||
totalMsgCountRoot
|
||||
lastRootPostAt
|
||||
team {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const allChannelsQuery = `
|
||||
query ${QueryNames.QUERY_ALL_CHANNELS}($perPage: Int!){
|
||||
channelMembers(userId:"me", first:$perPage) {
|
||||
cursor
|
||||
msgCount
|
||||
msgCountRoot
|
||||
mentionCount
|
||||
mentionCountRoot
|
||||
schemeAdmin
|
||||
lastViewedAt
|
||||
notifyProps
|
||||
roles {
|
||||
id
|
||||
name
|
||||
permissions
|
||||
}
|
||||
channel {
|
||||
id
|
||||
header
|
||||
purpose
|
||||
type
|
||||
createAt
|
||||
updateAt
|
||||
creatorId
|
||||
deleteAt
|
||||
displayName
|
||||
prettyDisplayName
|
||||
groupConstrained
|
||||
name
|
||||
shared
|
||||
lastPostAt
|
||||
totalMsgCount
|
||||
totalMsgCountRoot
|
||||
lastRootPostAt
|
||||
team {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const nextPageAllChannelsQuery = `
|
||||
query ${QueryNames.QUERY_ALL_CHANNELS_NEXT}($perPage: Int!, $cursor: String!) {
|
||||
channelMembers(userId:"me", first:$perPage, after:$cursor) {
|
||||
cursor
|
||||
msgCount
|
||||
msgCountRoot
|
||||
mentionCount
|
||||
mentionCountRoot
|
||||
schemeAdmin
|
||||
lastViewedAt
|
||||
notifyProps
|
||||
roles {
|
||||
id
|
||||
name
|
||||
permissions
|
||||
}
|
||||
channel {
|
||||
id
|
||||
header
|
||||
purpose
|
||||
type
|
||||
createAt
|
||||
updateAt
|
||||
creatorId
|
||||
deleteAt
|
||||
displayName
|
||||
prettyDisplayName
|
||||
groupConstrained
|
||||
name
|
||||
shared
|
||||
lastPostAt
|
||||
totalMsgCount
|
||||
totalMsgCountRoot
|
||||
lastRootPostAt
|
||||
team {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
export const MEMBERS_PER_PAGE = 200;
|
||||
|
|
@ -67,17 +67,17 @@ export function prepareMissingChannelsForAllTeams(operator: ServerDataOperator,
|
|||
}
|
||||
}
|
||||
|
||||
export const prepareMyChannelsForTeam = async (operator: ServerDataOperator, teamId: string, channels: Channel[], channelMembers: ChannelMembership[], isCRTEnabled?: boolean, isGraphQL = false) => {
|
||||
export const prepareMyChannelsForTeam = async (operator: ServerDataOperator, teamId: string, channels: Channel[], channelMembers: ChannelMembership[], isCRTEnabled?: boolean) => {
|
||||
const {database} = operator;
|
||||
|
||||
const channelsQuery = isGraphQL ? queryAllChannels(database) : queryAllChannelsForTeam(database, teamId);
|
||||
const channelsQuery = queryAllChannelsForTeam(database, teamId);
|
||||
const allChannelsForTeam = (await channelsQuery.fetch()).
|
||||
reduce((map: Record<string, ChannelModel>, channel) => {
|
||||
map[channel.id] = channel;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
const channelInfosQuery = isGraphQL ? queryAllChannelsInfo(database) : queryAllChannelsInfoForTeam(database, teamId);
|
||||
const channelInfosQuery = queryAllChannelsInfoForTeam(database, teamId);
|
||||
const allChannelsInfoForTeam = (await channelInfosQuery.fetch()).
|
||||
reduce((map: Record<string, ChannelInfoModel>, info) => {
|
||||
map[info.id] = info;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const {
|
|||
MY_CHANNEL,
|
||||
} = MM_TABLES.SERVER;
|
||||
|
||||
export async function prepareModels({operator, initialTeamId, removeTeams, removeChannels, teamData, chData, prefData, meData, isCRTEnabled}: PrepareModelsArgs, isGraphQL = false): Promise<Array<Promise<Model[]>>> {
|
||||
export async function prepareModels({operator, initialTeamId, removeTeams, removeChannels, teamData, chData, prefData, meData, isCRTEnabled}: PrepareModelsArgs): Promise<Array<Promise<Model[]>>> {
|
||||
const modelPromises: Array<Promise<Model[]>> = [];
|
||||
|
||||
if (removeTeams?.length) {
|
||||
|
|
@ -67,10 +67,8 @@ export async function prepareModels({operator, initialTeamId, removeTeams, remov
|
|||
}
|
||||
|
||||
if (chData?.channels?.length && chData.memberships?.length) {
|
||||
if (isGraphQL) {
|
||||
modelPromises.push(...await prepareMyChannelsForTeam(operator, '', chData.channels, chData.memberships, isCRTEnabled, true));
|
||||
} else if (initialTeamId) {
|
||||
modelPromises.push(...await prepareMyChannelsForTeam(operator, initialTeamId, chData.channels, chData.memberships, isCRTEnabled, false));
|
||||
if (initialTeamId) {
|
||||
modelPromises.push(...await prepareMyChannelsForTeam(operator, initialTeamId, chData.channels, chData.memberships, isCRTEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,215 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
const defaultNotifyProps: UserNotifyProps = {
|
||||
channel: 'true',
|
||||
comments: 'never',
|
||||
desktop: 'mention',
|
||||
desktop_sound: 'true',
|
||||
email: 'true',
|
||||
email_threads: 'all',
|
||||
first_name: 'false',
|
||||
mention_keys: '',
|
||||
push: 'mention',
|
||||
push_status: 'away',
|
||||
push_threads: 'all',
|
||||
|
||||
};
|
||||
export const gqlToClientUser = (u: Partial<GQLUser>): UserProfile => {
|
||||
return {
|
||||
id: u.id || '',
|
||||
create_at: u.createAt || 0,
|
||||
update_at: u.updateAt || 0,
|
||||
delete_at: u.deleteAt || 0,
|
||||
username: u.username || '',
|
||||
auth_service: u.authService || '',
|
||||
|
||||
email: u.email || '',
|
||||
email_verified: u.emailVerified ?? true,
|
||||
nickname: u.nickname || '',
|
||||
first_name: u.firstName || '',
|
||||
last_name: u.lastName || '',
|
||||
position: u.position || '',
|
||||
roles: u.roles?.map((v) => v.name!).join(' ') || '',
|
||||
locale: u.locale || '',
|
||||
notify_props: u.notifyProps || defaultNotifyProps,
|
||||
props: u.props,
|
||||
|
||||
timezone: u.timezone,
|
||||
is_bot: u.isBot,
|
||||
last_picture_update: u.lastPictureUpdate,
|
||||
remote_id: u.remoteId,
|
||||
status: u.status?.status || '',
|
||||
bot_description: u.botDescription,
|
||||
bot_last_icon_update: u.botLastIconUpdate,
|
||||
|
||||
terms_of_service_id: u.termsOfServiceId || '',
|
||||
terms_of_service_create_at: u.termsOfServiceCreateAt || 0,
|
||||
|
||||
auth_data: '',
|
||||
};
|
||||
};
|
||||
|
||||
export const gqlToClientSession = (s: Partial<GQLSession>): Session => {
|
||||
return {
|
||||
create_at: s.createAt || 0,
|
||||
expires_at: s.expiresAt || 0,
|
||||
id: '',
|
||||
user_id: '',
|
||||
};
|
||||
};
|
||||
|
||||
export const gqlToClientTeamMembership = (m: Partial<GQLTeamMembership>, userId?: string): TeamMembership => {
|
||||
return {
|
||||
team_id: m.team?.id || '',
|
||||
delete_at: m.deleteAt || 0,
|
||||
roles: m.roles?.map((v) => v.name!).join(' ') || '',
|
||||
user_id: m.user?.id || userId || '',
|
||||
scheme_admin: m.schemeAdmin || false,
|
||||
scheme_user: m.schemeUser || false,
|
||||
mention_count: 0,
|
||||
msg_count: 0,
|
||||
};
|
||||
};
|
||||
|
||||
export const gqlToClientSidebarCategory = (c: Partial<GQLSidebarCategory>, teamId: string): CategoryWithChannels => {
|
||||
return {
|
||||
channel_ids: c.channelIds || [],
|
||||
collapsed: c.collapsed || false,
|
||||
display_name: c.displayName || '',
|
||||
id: c.id || '',
|
||||
muted: c.muted || false,
|
||||
sort_order: c.sortOrder || 0,
|
||||
sorting: c.sorting || 'alpha',
|
||||
team_id: c.teamId || teamId,
|
||||
type: c.type || 'channels',
|
||||
};
|
||||
};
|
||||
|
||||
export const gqlToClientTeam = (t: Partial<GQLTeam>): Team => {
|
||||
return {
|
||||
allow_open_invite: t.allowOpenInvite || false,
|
||||
allowed_domains: t.allowedDomains || '',
|
||||
company_name: t.companyName || '',
|
||||
create_at: t.createAt || 0,
|
||||
delete_at: t.deleteAt || 0,
|
||||
description: t.description || '',
|
||||
display_name: t.displayName || '',
|
||||
email: t.email || '',
|
||||
group_constrained: t.groupConstrained || false,
|
||||
id: t.id || '',
|
||||
invite_id: t.inviteId || '',
|
||||
last_team_icon_update: t.lastTeamIconUpdate || 0,
|
||||
name: t.name || '',
|
||||
scheme_id: t.schemeId || '',
|
||||
type: t.type || 'I',
|
||||
update_at: t.updateAt || 0,
|
||||
|
||||
// cloudLimitsArchived and policyId not used
|
||||
};
|
||||
};
|
||||
|
||||
export const gqlToClientPreference = (p: Partial<GQLPreference>): PreferenceType => {
|
||||
return {
|
||||
category: p.category || '',
|
||||
name: p.name || '',
|
||||
user_id: p.userId || '',
|
||||
value: p.value || '',
|
||||
};
|
||||
};
|
||||
|
||||
export const gqlToClientChannelMembership = (m: Partial<GQLChannelMembership>, userId?: string): ChannelMembership => {
|
||||
return {
|
||||
channel_id: m.channel?.id || '',
|
||||
last_update_at: m.lastUpdateAt || 0,
|
||||
last_viewed_at: m.lastViewedAt || 0,
|
||||
mention_count: m.mentionCount || 0,
|
||||
mention_count_root: m.mentionCountRoot || 0,
|
||||
msg_count: m.msgCount || 0,
|
||||
msg_count_root: m.msgCountRoot || 0,
|
||||
notify_props: m.notifyProps || {},
|
||||
roles: m.roles?.map((r) => r.name).join(' ') || '',
|
||||
user_id: m.user?.id || userId || '',
|
||||
is_unread: false,
|
||||
last_post_at: 0,
|
||||
post_root_id: '',
|
||||
scheme_admin: m.schemeAdmin,
|
||||
scheme_user: m.schemeUser,
|
||||
};
|
||||
};
|
||||
|
||||
export const gqlToClientChannel = (c: Partial<GQLChannel>, teamId?: string): Channel => {
|
||||
return {
|
||||
create_at: c.createAt || 0,
|
||||
creator_id: c.creatorId || '',
|
||||
delete_at: c.deleteAt || 0,
|
||||
display_name: c.prettyDisplayName || c.displayName || '',
|
||||
extra_update_at: 0,
|
||||
group_constrained: c.groupConstrained || false,
|
||||
header: c.header || '',
|
||||
id: c.id || '',
|
||||
last_post_at: c.lastPostAt || 0,
|
||||
last_root_post_at: c.lastRootPostAt || 0,
|
||||
name: c.name || '',
|
||||
purpose: c.purpose || '',
|
||||
scheme_id: c.schemeId || '',
|
||||
shared: c.shared || false,
|
||||
team_id: c.team?.id || teamId || '',
|
||||
total_msg_count: c.totalMsgCount || 0,
|
||||
total_msg_count_root: c.totalMsgCountRoot || 0,
|
||||
type: c.type || 'O',
|
||||
update_at: c.updateAt || 0,
|
||||
fake: false,
|
||||
isCurrent: false,
|
||||
status: '',
|
||||
teammate_id: '',
|
||||
};
|
||||
};
|
||||
|
||||
export const gqlToClientChannelStats = (s: Partial<GQLChannel>): ChannelStats => {
|
||||
return {
|
||||
channel_id: s.id || '',
|
||||
guest_count: s.stats?.guestCount || 0,
|
||||
member_count: s.stats?.memberCount || 0,
|
||||
pinnedpost_count: s.stats?.pinnePostCount || 0,
|
||||
files_count: s.stats?.filesCount || 0,
|
||||
};
|
||||
};
|
||||
|
||||
export const gqlToClientRole = (r: Partial<GQLRole>): Role => {
|
||||
return {
|
||||
id: r.id || '',
|
||||
name: r.name || '',
|
||||
permissions: r.permissions || [],
|
||||
built_in: r.builtIn,
|
||||
scheme_managed: r.schemeManaged,
|
||||
};
|
||||
};
|
||||
|
||||
export const getMemberChannelsFromGQLQuery = (data: GQLData) => {
|
||||
return data.channelMembers?.reduce<Channel[]>((acc, m) => {
|
||||
if (m.channel) {
|
||||
acc.push(gqlToClientChannel(m.channel));
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const getMemberTeamsFromGQLQuery = (data: GQLData) => {
|
||||
return data.teamMembers?.reduce<Team[]>((acc, m) => {
|
||||
if (m.team) {
|
||||
acc.push(gqlToClientTeam(m.team));
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const filterAndTransformRoles = (roles: Array<Partial<GQLRole> | undefined>) => {
|
||||
const byName = roles.reduce<{[name: string]: Partial<GQLRole>}>((acum, r) => {
|
||||
if (r?.name && !acum[r.name]) {
|
||||
acum[r.name] = r;
|
||||
}
|
||||
return acum;
|
||||
}, {});
|
||||
return Object.values(byName).map((r) => gqlToClientRole(r));
|
||||
};
|
||||
1
types/api/config.d.ts
vendored
1
types/api/config.d.ts
vendored
|
|
@ -119,7 +119,6 @@ interface ClientConfig {
|
|||
ExtendSessionLengthWithActivity: string;
|
||||
FeatureFlagAppsEnabled?: string;
|
||||
FeatureFlagCollapsedThreads?: string;
|
||||
FeatureFlagGraphQL?: string;
|
||||
FeatureFlagPostPriority?: string;
|
||||
ForgotPasswordLink?: string;
|
||||
GfycatApiKey: string;
|
||||
|
|
|
|||
186
types/api/graphql.d.ts
vendored
186
types/api/graphql.d.ts
vendored
|
|
@ -1,186 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
type GQLResponse = {
|
||||
errors?: GQLError[];
|
||||
data: GQLData;
|
||||
}
|
||||
|
||||
type GQLData = {
|
||||
user?: Partial<GQLUser>;
|
||||
config?: ClientConfig;
|
||||
license?: ClientLicense;
|
||||
teamMembers: Array<Partial<GQLTeamMembership>>;
|
||||
channels?: Array<Partial<GQLChannel>>;
|
||||
channelsLeft?: Array<Partial<GQLChannel>>;
|
||||
channelMembers?: Array<Partial<GQLChannelMembership>>;
|
||||
sidebarCategories?: Array<Partial<GQLSidebarCategory>>;
|
||||
}
|
||||
|
||||
type GQLError = {
|
||||
message: string;
|
||||
path: Array<string | number>;
|
||||
}
|
||||
|
||||
type GQLUser = {
|
||||
id: string;
|
||||
createAt: number;
|
||||
updateAt: number;
|
||||
deleteAt: number;
|
||||
username: string;
|
||||
authService: string;
|
||||
email: string;
|
||||
emailVerified: boolean;
|
||||
nickname: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
position: string;
|
||||
locale: string;
|
||||
notifyProps: UserNotifyProps;
|
||||
props: UserProps;
|
||||
timezone: UserTimezone;
|
||||
isBot: boolean;
|
||||
lastPictureUpdate: number;
|
||||
remoteId: string;
|
||||
botDescription: string;
|
||||
botLastIconUpdate: number;
|
||||
termsOfServiceId: string;
|
||||
termsOfServiceCreateAt: number;
|
||||
|
||||
roles: Array<Partial<GQLRole>>;
|
||||
customStatus: Partial<GQLUserCustomStatus>;
|
||||
status: Partial<GQLUserStatus>;
|
||||
preferences: Array<Partial<GQLPreference>>;
|
||||
sessions: Array<Partial<GQLSession>>;
|
||||
|
||||
// Derived
|
||||
isSystemAdmin: boolean;
|
||||
isGuest: boolean;
|
||||
}
|
||||
|
||||
type GQLSession = {
|
||||
createAt: number;
|
||||
expiresAt: number;
|
||||
}
|
||||
|
||||
type GQLTeamMembership = {
|
||||
team: Partial<GQLTeam>;
|
||||
user: Partial<GQLUser>;
|
||||
roles: Array<Partial<GQLRole>>;
|
||||
deleteAt: number;
|
||||
schemeGuest: boolean;
|
||||
schemeUser: boolean;
|
||||
schemeAdmin: boolean;
|
||||
}
|
||||
|
||||
type GQLSidebarCategory = {
|
||||
id: string;
|
||||
sorting: CategorySorting;
|
||||
type: CategoryType;
|
||||
displayName: string;
|
||||
muted: boolean;
|
||||
collapsed: boolean;
|
||||
channelIds: string[];
|
||||
sortOrder: number;
|
||||
teamId: string;
|
||||
}
|
||||
|
||||
type GQLTeam = {
|
||||
id: string;
|
||||
displayName: string;
|
||||
name: string;
|
||||
description: string;
|
||||
email: string;
|
||||
type: TeamType;
|
||||
companyName: string;
|
||||
allowedDomains: string;
|
||||
inviteId: string;
|
||||
lastTeamIconUpdate: number;
|
||||
groupConstrained: boolean;
|
||||
allowOpenInvite: boolean;
|
||||
updateAt: number;
|
||||
createAt: number;
|
||||
deleteAt: number;
|
||||
schemeId: string;
|
||||
policyId: string;
|
||||
cloudLimitsArchived: boolean;
|
||||
}
|
||||
|
||||
type GQLUserCustomStatus = {
|
||||
emoji: string;
|
||||
text: string;
|
||||
duration: CustomStatusDuration;
|
||||
expiresAt: string;
|
||||
}
|
||||
|
||||
type GQLUserStatus = {
|
||||
status: string;
|
||||
manual: boolean;
|
||||
lastActivityAt: number;
|
||||
activeChannel: string;
|
||||
dndEndTime: number;
|
||||
}
|
||||
|
||||
type GQLPreference = {
|
||||
userId: string;
|
||||
category: string;
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
type GQLChannelMembership = {
|
||||
channel: Partial<GQLChannel>;
|
||||
user: Partial<GQLUser>;
|
||||
roles: Array<Partial<GQLRole>>;
|
||||
lastViewedAt: number;
|
||||
msgCount: number;
|
||||
msgCountRoot: number;
|
||||
mentionCount: number;
|
||||
mentionCountRoot: number;
|
||||
notifyProps: ChannelNotifyProps;
|
||||
lastUpdateAt: number;
|
||||
schemeGuest: boolean;
|
||||
schemeUser: boolean;
|
||||
schemeAdmin: boolean;
|
||||
explicitRoles: string;
|
||||
cursor: string;
|
||||
}
|
||||
|
||||
type GQLChannel = {
|
||||
id: string;
|
||||
createAt: number;
|
||||
updateAt: number;
|
||||
deleteAt: number;
|
||||
type: ChannelType;
|
||||
displayName: string;
|
||||
prettyDisplayName: string;
|
||||
name: string;
|
||||
header: string;
|
||||
purpose: string;
|
||||
creatorId: string;
|
||||
schemeId: string;
|
||||
team: Partial<GQLTeam>;
|
||||
cursor: string;
|
||||
groupConstrained: boolean;
|
||||
shared: boolean;
|
||||
lastPostAt: number;
|
||||
lastRootPostAt: number;
|
||||
totalMsgCount: number;
|
||||
totalMsgCountRoot: number;
|
||||
stats: Partial<GQLStats>;
|
||||
}
|
||||
|
||||
type GQLStats = {
|
||||
guestCount: number;
|
||||
memberCount: number;
|
||||
pinnePostCount: number;
|
||||
filesCount: number;
|
||||
}
|
||||
|
||||
type GQLRole = {
|
||||
id: string;
|
||||
name: string;
|
||||
permissions: string[];
|
||||
schemeManaged: boolean;
|
||||
builtIn: boolean;
|
||||
}
|
||||
Loading…
Reference in a new issue