Forum Discussion

johnjohn-Peter's avatar
johnjohn-Peter
Iron Contributor
Oct 26, 2024

How i can reOrder the Channel Tabs using graph API inside our Teams apps

I am working on a Teams App >> which creates a new SharePoint modern Teams Site + new Channels + tabs inside the channels.

The final result will be as follow: -

 

 

Now I want to reorder the tabs inside the General channel, mainly by moving the Notes tab to be the last tab, here is the method i have which mainly sets the sortOrderIndex for the Notes tab to be "6": -

 

//ReOrder General Channel Tabs
 
 public async reorderTabs(graph: any, teamGroupId: any, channelID: string, tabName: string) {
            try {
                //get URL for the tab
                const tabsGraphEndPoint = graphConfig.teamsGraphEndpoint + "/" + teamGroupId + graphConfig.channelsGraphEndpoint + "/" + channelID + graphConfig.tabsGraphEndpoint;
    
                const tabs = await this.getGraphData(tabsGraphEndPoint, graph)
                // Find the "Notes" tab
                const notesTab = tabs.value.find((tab: any) => tab.displayName === "Notes");

                if (notesTab) 
                    {
                      // Update the orderHint to move the "Notes" tab to the end
                         const updateTabEndpoint = graphConfig.teamsGraphEndpoint + "/" + teamGroupId + graphConfig.channelsGraphEndpoint + "/" + channelID + graphConfig.tabsGraphEndpoint + "/"+ notesTab.id;
                         const lastOrderHint = tabs.value[tabs.value.length - 1].orderHint;

                         // Set the orderHint to something greater than the last tab's orderHint
                         const newOrderHint = "6";

                         await this.sendGraphPatchRequest(updateTabEndpoint, graph, {
                                    sortOrderIndex: newOrderHint
                    });
                    return notesTab.displayName;
                    }
            } catch (error) {
                console.error(
                    constants.errorLogPrefix + "CommonService_getTabURL \n",
                    JSON.stringify(error)
                );
                throw error;
            }
        }

 

 

Here is the main method inside the .tsx file:-

 

 

// wrapper method to perform teams related operations
    private async createTeamAndChannels(incidentId: any) {
        try {
            console.log(constants.infoLogPrefix + "M365 group creation starts");
            // call method to create Teams group
            const groupInfo = await this.createTeamGroup(incidentId);
            try {
                console.log(constants.infoLogPrefix + "M365 group created");

                // create associated team with the group
                const teamInfo = await this.createTeam(groupInfo);
                if (teamInfo.status) {
                    //log trace
                    this.dataService.trackTrace(this.props.appInsights, "Incident Team created ", incidentId, this.props.userPrincipalName);

                    //Send invitations to the guest users
                    let returnInvitationObj: any;
                    if (this.state.toggleGuestUsers)
                        returnInvitationObj = this.sendInvitation(groupInfo.id, teamInfo.data.displayName, teamInfo.data.webUrl)

                    // create channels
                    await this.createChannels(teamInfo.data);

                    this.setState({ loaderMessage: this.props.localeStrings.createPlanloaderMessage });

                    //Get General channel id
                    const generalChannelId = await this.dataService.getChannelId(this.props.graph,
                        groupInfo.id, constants.General);

                    //Add TEOC app to the Incident Team General channel's Active Dashboard Tab
                    await this.dataService.createActiveDashboardTab(this.props.graph, groupInfo.id,
                        generalChannelId, this.props.graphContextURL, this.props.appSettings);

                    //Create planner with the Group ID                        
                    const planID = await this.dataService.createPlannerPlan(groupInfo.id, incidentId, this.props.graph,
                        this.props.graphContextURL, this.props.tenantID, generalChannelId, false);

                    //added for GCCH tenant
                    if (this.props.graphBaseUrl !== constants.defaultGraphBaseURL) {
                        // wait for 5 seconds to ensure the SharePoint site is available via graph API
                        await this.timeout(5000);
                    }

                    // graph endpoint to get team site Id
                    const teamSiteURLGraphEndpoint = graphConfig.teamGroupsGraphEndpoint + "/" +
                        groupInfo.id + graphConfig.rootSiteGraphEndpoint;

                    // retrieve team site details
                    const teamSiteDetails = await this.dataService.getGraphData(teamSiteURLGraphEndpoint, this.props.graph);

                    //get the team site managed path
                    const teamSiteManagedPathURL = teamSiteDetails.webUrl.split(teamSiteDetails.siteCollection.hostname)[1];
                    console.log(constants.infoLogPrefix + "Site ManagedPath", teamSiteManagedPathURL);

                    // create news channel and tab
                    const newsTabLink = await this.createNewsTab(groupInfo, teamSiteDetails.webUrl, teamSiteManagedPathURL,groupInfo.id);

                    // create assessment channel and tab
                   // await this.createAssessmentChannelAndTab(groupInfo.id, teamSiteDetails.webUrl, teamSiteManagedPathURL);

                    // call method to create assessment list
                    //await this.createAssessmentList(groupInfo.mailNickname, teamSiteDetails.id);
                    //Reorder Tabs
                    const tabname = await this.dataService.reorderTabs(this.props.graph,teamInfo.data.id,generalChannelId,"Notes");
                    console.log(constants.infoLogPrefix + "Reorder General channel Tabs");
                    //log trace
                    this.dataService.trackTrace(this.props.appInsights, "Assessment list created ", incidentId, this.props.userPrincipalName);

                    //change the M365 group visibility to Private for GCCH tenant
                    if (this.props.graphBaseUrl !== constants.defaultGraphBaseURL) {
                        this.graphEndpoint = graphConfig.teamGroupsGraphEndpoint + "/" + groupInfo.id;
                        await this.dataService.sendGraphPatchRequest(this.graphEndpoint, this.props.graph, { "visibility": "Private" })
                        console.log(constants.infoLogPrefix + "Group setting changed to Private");
                    }

                    //Update Team details, Plan ID, NewsTabLink in Incident Transation List                                   
                    const updateItemObj = {
                        IncidentId: incidentId,
                        TeamWebURL: teamInfo.data.webUrl,
                        PlanID: planID,
                        NewsTabLink: newsTabLink
                    };

                    await this.updateIncidentItemInList(incidentId, updateItemObj);
                    console.log(constants.infoLogPrefix + "List item updated");

                    let roles: any = this.state.roleAssignments;
                    roles.push({
                        role: constants.incidentCommanderRoleName,
                        userNamesString: this.state.incDetailsItem.incidentCommander.userName,
                        userDetailsObj: [this.state.incDetailsItem.incidentCommander]
                    });

                    //post incident message in General Channel
                    await this.postIncidentMessage(groupInfo.id);

                    // create the tags for incident commander and each selected roles                        
                    await this.createTagObject(teamInfo.data.id, roles);
                    //log trace
                    this.dataService.trackTrace(this.props.appInsights, "Tags are created ", incidentId, this.props.userPrincipalName);
                    Promise.allSettled([returnInvitationObj]).then((promiseObj: any) => {
                        this.setState({
                            showLoader: false,
                            formOpacity: 1
                        });

                        // Display success message if incident updated successfully
                        this.props.showMessageBar(this.props.localeStrings.incidentCreationSuccessMessage, constants.messageBarType.success);

                        // Display error message if guest invitations
                        if ((promiseObj[0]?.value !== undefined && !promiseObj[0].value?.isAllSucceeded))
                            this.props.showMessageBar(
                                ((promiseObj[0]?.value !== undefined && !promiseObj[0]?.value?.isAllSucceeded) ? " " + promiseObj[0]?.value?.message + ". " : ""),
                                constants.messageBarType.error);
                        this.props.onBackClick(constants.messageBarType.success);
                    });

                }
                else {
                    // delete the group if some error occured
                    await this.deleteTeamGroup(groupInfo.id);
                    // delete the item if error occured
                    await this.deleteIncident(incidentId);

                    this.setState({
                        showLoader: false,
                        formOpacity: 1
                    })
                    this.props.showMessageBar(this.props.localeStrings.genericErrorMessage + ", " + this.props.localeStrings.errMsgForCreateIncident, constants.messageBarType.error);
                }
            }
            catch (error) {
                console.error(
                    constants.errorLogPrefix + "CreateIncident_createTeamAndChannels \n",
                    JSON.stringify(error)
                );
                // Log Exception
                this.dataService.trackException(this.props.appInsights, error, constants.componentNames.IncidentDetailsComponent, 'CreateIncident_createTeamAndChannels', this.props.userPrincipalName);
                // delete the group if some error occured
                await this.deleteTeamGroup(groupInfo.id);
                // delete the item if error occured
                await this.deleteIncident(incidentId);

                this.setState({
                    showLoader: false,
                    formOpacity: 1
                })
                this.props.showMessageBar(this.props.localeStrings.genericErrorMessage + ", " + this.props.localeStrings.errMsgForCreateIncident, constants.messageBarType.error);
            }
        }
        catch (error: any) {
            console.error(
                constants.errorLogPrefix + "CreateIncident_createTeamAndChannels \n",
                JSON.stringify(error)
            );
            // Log Exception
            this.dataService.trackException(this.props.appInsights, error, constants.componentNames.IncidentDetailsComponent, 'CreateIncident_createTeamAndChannels', this.props.userPrincipalName);

            // delete the item if error occured
            this.deleteIncident(incidentId);

            this.setState({
                showLoader: false,
                formOpacity: 1
            });

            // Display error message if M365 group creation fails with access denied error
            if (error?.statusCode === 403 && error?.code === constants.authorizationRequestDenied
                && error?.message === constants.groupCreationAccessDeniedErrorMessage) {
                this.props.showMessageBar(this.props.localeStrings.genericErrorMessage + ", " + this.props.localeStrings.m365GroupCreationFailedMessage, constants.messageBarType.error);
            }
            /* Display error message if M365 group creation fails with group already exists error 
            or any other error */
            else {
                this.props.showMessageBar(this.props.localeStrings.genericErrorMessage + ", " + this.props.localeStrings.errMsgForCreateIncident, constants.messageBarType.error);
            }
        }
    }

 

But after calling the above method during the site and channel creation the Notes will stay the 3rd tab. any advice?

No RepliesBe the first to reply

Resources