Создание приложения вкладки панели мониторинга
Панель мониторинга — это инструмент для отслеживания, анализа и отображения данных для получения аналитических сведений об организации или конкретном процессе. Панели мониторинга в Teams позволяют отслеживать и просматривать важные метрики.
Шаблон вкладки панели мониторинга из набора средств Teams позволяет приступить к интеграции холста с несколькими карточками, которые предоставляют обзор содержимого в Teams. Варианты действий:
- Используйте мини-приложения для отображения содержимого из приложений и служб на вкладке панели мониторинга.
- Интеграция приложения с API Graph для визуализации сведений о реализации выбранных данных.
- Создавайте настраиваемые панели мониторинга, которые позволяют вашей компании задавать определенные цели, которые помогут вам отслеживать информацию, необходимую для просмотра в нескольких областях и в разных отделах.
Ваша команда может получать последние обновления из разных источников в Teams с помощью приложения вкладки панели мониторинга Teams. Используйте приложения вкладки панели мониторинга для подключения многочисленных метрик, источников данных, API и служб. Приложения вкладки панели мониторинга помогают вашей организации извлекать релевантную информацию из источников и представлять ее пользователям. Дополнительные сведения о создании приложения вкладки панели мониторинга см. в пошаговом руководстве.
Добавление новой панели мониторинга
После создания приложения вкладки панели мониторинга можно добавить новую панель мониторинга.
Чтобы добавить новую панель мониторинга, выполните следующие действия.
- Создание класса панели мониторинга
- Переопределение методов для настройки приложения вкладки панели мониторинга
- Добавление маршрута для нового приложения вкладки панели мониторинга
- Изменение манифеста для добавления нового приложения вкладки панели мониторинга
Создание класса панели мониторинга
Создайте файл с расширением .tsx
для панели мониторинга в каталоге src/dashboards
, например YourDashboard.tsx
. Затем создайте класс, расширяющий BaseDashboard class from
@microsoft/teamsfx-react.
// Create a dashboard class - https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/build-a-dashboard-tab-app#create-a-dashboard-class
import { BaseDashboard } from "@microsoft/teamsfx-react";
export default class SampleDashboard extends BaseDashboard { }
Примечание.
Все методы являются необязательными. Если ни один метод не переопределен, используется макет панели мониторинга по умолчанию.
Переопределение методов для настройки приложения вкладки панели мониторинга
Класс BaseDashboard
предоставляет несколько методов, которые можно переопределить для настройки макета панели мониторинга. В следующей таблице перечислены методы, которые можно переопределить:
Методы | Function |
---|---|
styling() |
Настройка стиля панели мониторинга. |
layout() |
Определение макета мини-приложений. |
Ниже приведен пример кода для настройки макета панели мониторинга:
.your-dashboard-layout {
grid-template-columns: 6fr 4fr;
}
import { BaseDashboard } from "@microsoft/teamsfx-react";
import ListWidget from "../widgets/ListWidget";
import ChartWidget from "../widgets/ChartWidget";
export default class YourDashboard extends BaseDashboard {
styling() {
return "your-dashboard-layout";
}
layout() {
return (
<>
<ListWidget />
<ChartWidget />
</>
);
}
}
Добавление маршрута для нового приложения вкладки панели мониторинга
Необходимо связать мини-приложение с файлом источника данных. Мини-приложение берет данные, представленные на панели мониторинга, из исходного файла.
src/App.tsx
Откройте файл и добавьте маршрут для новой панели мониторинга. Пример:
import YourDashboard from "./dashboards/YourDashboard";
export default function App() {
...
<Route path="/yourdashboard" element={<yourdashboard />} />
...
}
Изменение манифеста для добавления нового приложения вкладки панели мониторинга
appPackage/manifest.json
Откройте файл и добавьте новую вкладку панели мониторинга в разделе staticTabs
. Дополнительные сведения см. в манифесте приложения. Пример:
{
"entityId": "index1",
"name": "Your Dashboard",
"contentUrl": "${{TAB_ENDPOINT}}/index.html#/yourdashboard",
"websiteUrl": "${{TAB_ENDPOINT}}/index.html#/yourdashboard",
"scopes": ["personal"]
}
Настройка макета панели мониторинга
TeamsFx предоставляет удобные методы для определения и изменения макета панели мониторинга. Ниже приведены методы.
Три мини-приложения подряд с высотой 350 пикселей, занимающих 20 процентов, 60 процентов и 20 процентов ширины соответственно.
.customize-class-name { grid-template-rows: 350px; grid-template-columns: 2fr 6fr 2fr; }
export default class SampleDashboard extends BaseDashboard { styling() { return "customize-class-name"; } layout() { return ( <> <ListWidget /> <ChartWidget /> <NewsWidget /> </> ); } }
Два мини-приложения в строке с шириной 600 пикселей и 1100 пикселей. Высота первой строки — это максимальная высота ее содержимого, а высота второй строки — 400 пикселей.
.customize-class-name { grid-template-rows: max-content 400px; grid-template-columns: 600px 1100px; }
export default class SampleDashboard extends Dashboard { styling() { return "customize-class-name"; } layout() { return ( <> <ListWidget /> <ChartWidget /> <NewsWidget /> </> ); } }
Расположите два мини-приложения в столбце.
.one-column { display: grid; gap: 20px; grid-template-rows: 1fr 1fr; }
export default class SampleDashboard extends BaseDashboard { layout() { return ( <> <ListWidget /> <ChartWidget /> </> ); } }
Абстракция приложения вкладки панели мониторинга
Чтобы настроить макет панели мониторинга, TeamsFx предоставляет BaseDashboard
разработчикам класс для реализации панели мониторинга.
Следующий код является примером BaseDashboard
класса :
function dashboardStyle(isMobile?: boolean) {
return mergeStyles({
display: "grid",
gap: "20px",
padding: "20px",
gridTemplateRows: "1fr",
gridTemplateColumns: "4fr 6fr",
...(isMobile === true ? { gridTemplateColumns: "1fr", gridTemplateRows: "1fr" } : {}),
});
}
interface BaseDashboardState {
isMobile?: boolean;
showLogin?: boolean;
observer?: ResizeObserver;
}
export class BaseDashboard<P, S> extends Component<P, S & BaseDashboardState> {
private ref: React.RefObject<HTMLDivElement>;
public constructor(props: Readonly<P>) {
super(props);
this.state = {
isMobile: undefined,
showLogin: undefined,
observer: undefined,
} as S & BaseDashboardState;
this.ref = React.createRef<HTMLDivElement>();
}
public async componentDidMount() {
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
if (entry.target === this.ref.current) {
const { width } = entry.contentRect;
this.setState({ isMobile: width < 600 } as S & BaseDashboardState);
}
}
});
observer.observe(this.ref.current!);
}
public componentWillUnmount(): void {
if (this.state.observer && this.ref.current) {
this.state.observer.unobserve(this.ref.current);
}
}
public render() {
return (
<div
ref={this.ref}
className={mergeStyles(dashboardStyle(this.state.isMobile), this.styling())}
>
{this.layout()}
</div>
);
}
protected layout(): JSX.Element | undefined {
return undefined;
}
protected styling(): string {
return null;
}
}
BaseDashboard
В классе TeamsFx предоставляет базовые макеты с настраиваемыми методами. Панель мониторинга по-прежнему является компонентом react, и TeamsFx предоставляет базовые реализации функций на основе жизненного цикла компонентов react, таких как:
- Реализация базовой логики отрисовки на основе макета сетки.
- Добавление наблюдателя для автоматической адаптации к мобильным устройствам.
Ниже приведены настраиваемые методы для переопределения.
Методы | Функция | Рекомендуется переопределить |
---|---|---|
constructor() |
Инициализирует состояние панели мониторинга и переменные. | Нет |
componentDidMount() |
Вызывается после подключения компонента. | Нет |
componentWillUnmount() |
Вызывается при отключении компонента. | Нет |
render() |
Вызывается при наличии обновления. В этом методе определен макет панели мониторинга по умолчанию. | Нет |
layout |
Определяет макет мини-приложения на панели мониторинга. Этот метод можно переопределить. | Да |
styling() |
Настройка стиля панели мониторинга. Этот метод можно переопределить. | Да |
Использование мини-приложения на панели мониторинга
Мини-приложения отображают настраиваемую информацию и диаграммы на панелях мониторинга. Они отображаются на доске мини-приложений, где можно закрепить, открепить, упорядочить, изменить размер и настроить мини-приложения в соответствии с вашими интересами. Ваша доска мини-приложений оптимизирована для отображения соответствующих мини-приложений и персонализированного содержимого в зависимости от использования.
Настройка мини-приложения
Мини-приложение можно настроить, переопределив следующие методы в BaseWidget
классе :
Переопределите
header()
,body()
иfooter()
, чтобы настроить мини-приложение.export class NewsWidget extends BaseWidget<any, any> { override header(): JSX.Element | undefined { return ( <div> <News28Regular /> <Text>Your News</Text> <Button icon={<MoreHorizontal32Regular />} appearance="transparent" /> </div> ); } override body(): JSX.Element | undefined { return ( <div> <Image src="image.svg" /> <Text>Lorem Ipsum Dolor</Text> <Text> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim, elementum sed </Text> </div> ); } override footer(): JSX.Element | undefined { return ( <Button appearance="transparent" icon={<ArrowRight16Filled />} iconPosition="after" size="small" > View details </Button> ); } }
Переопределите
body()
иfooter()
настройте мини-приложение.export class NewsWidget extends BaseWidget<any, any> { override body(): JSX.Element | undefined { return ( <div> <Image src="image.svg" /> <Text>Lorem Ipsum Dolor</Text> <Text> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim, elementum sed </Text> </div> ); } override footer(): JSX.Element | undefined { return ( <Button appearance="transparent" icon={<ArrowRight16Filled />} iconPosition="after" size="small" > View details </Button> ); } }
Переопределите
body()
, чтобы настроить мини-приложение.export class NewsWidget extends BaseWidget<any, any> { override body(): JSX.Element | undefined { return ( <div> <Image src="image.svg" /> <Text>Lorem Ipsum Dolor</Text> <Text> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim, elementum sed </Text> </div> ); } }
Включение загрузчика данных
Если вы хотите включить загрузчик данных в мини-приложение перед загрузкой мини-приложения, можно добавить свойство в состояние мини-приложения, чтобы указать, что загрузчик данных имеет значение loading()
. Это свойство можно использовать для отображения индикатора загрузки пользователю.
Пример:
override loading(): JSX.Element | undefined {
return (
<div className="loading">
<Spinner label="Loading..." labelPosition="below" />
</div>
);
}
Теперь при загрузке данных отображается модуль загрузки. При загрузке данных загрузочный модуль скрывается, а также отображаются кнопка со списком данных и нижнего колонтитула.
Обработка пустого состояния
Вы можете отобразить определенное содержимое в мини-приложении, если данные пусты. Для этого необходимо изменить body
метод в файле мини-приложения, чтобы он принял различные состояния данных.
В следующем примере показано, как отобразить пустое изображение, если данные ListWidget пусты.
override body(): JSX.Element | undefined {
let hasData = this.state.data && this.state.data.length > 0;
return (
<div>
{hasData ? (
<>
{this.state.data?.map((t: ListModel) => {
...
})}
</>
) : (
<div>
<Image src="empty-default.svg" height="150px" />
<Text align="center">No data</Text>
</div>
)}
</div>
);
}
Аналогичный подход можно использовать для удаления содержимого нижнего колонтитула мини-приложения, если данные пусты.
override footer(): JSX.Element | undefined {
let hasData = this.state.data && this.state.data.length > 0;
if (hasData) {
return <Button>...</Button>;
}
}
Если данные пусты, мини-приложение списка отображается следующим образом:
Обновление данных по расписанию
В следующем примере показано, как отображать данные в режиме реального времени в мини-приложении. Мини-приложение отображает текущее время и обновления.
interface IRefreshWidgetState {
data: string;
}
export class RefreshWidget extends BaseWidget<any, IRefreshWidgetState> {
override body(): JSX.Element | undefined {
return <>{this.state.data}</>;
}
async componentDidMount() {
setInterval(() => {
this.setState({ data: new Date().toLocaleTimeString() });
}, 1000);
}
}
Вы можете изменить setInterval
метод, чтобы вызвать собственную функцию для обновления данных, как показано ниже setInterval(() => yourGetDataFunction(), 1000)
.
Абстракция мини-приложения
Чтобы упростить разработку мини-приложения, Пакет SDK TeamsFx предоставляет BaseWidget
класс для разработчиков, который наследует, чтобы реализовать мини-приложение, соответствующее их потребностям, не уделяя особого внимания реализации макета мини-приложения.
Следующий код является примером класса BaseWidget:
export interface IWidgetClassNames {
root?: string;
header?: string;
body?: string;
footer?: string;
}
const classNames: IWidgetClassNames = mergeStyleSets({
root: {
display: "grid",
padding: "1.25rem 2rem 1.25rem 2rem",
backgroundColor: tokens.colorNeutralBackground1,
border: "1px solid var(--colorTransparentStroke)",
boxShadow: tokens.shadow4,
borderRadius: tokens.borderRadiusMedium,
gap: tokens.spacingHorizontalL,
gridTemplateRows: "max-content 1fr max-content",
},
header: {
display: "grid",
height: "max-content",
"& div": {
display: "grid",
gap: tokens.spacingHorizontalS,
alignItems: "center",
gridTemplateColumns: "min-content 1fr min-content",
},
"& svg": {
height: "1.5rem",
width: "1.5rem",
},
"& span": {
fontWeight: tokens.fontWeightSemibold,
lineHeight: tokens.lineHeightBase200,
fontSize: tokens.fontSizeBase200,
},
},
footer: {
"& button": {
width: "fit-content",
},
},
});
interface BaseWidgetState {
loading?: boolean;
}
export class BaseWidget<P, S> extends Component<P, S & BaseWidgetState> {
public constructor(props: Readonly<P>) {
super(props);
this.state = { loading: undefined } as S & BaseWidgetState;
}
public async componentDidMount() {
this.setState({ ...(await this.getData()), loading: false });
}
public render() {
const { root, header, body, footer } = this.styling();
const showLoading = this.state.loading !== false && this.loading() !== undefined;
return (
<div className={mergeStyles(classNames.root, root)}>
{this.header() && (
<div className={mergeStyles(classNames.header, header)}>{this.header()}</div>
)}
{showLoading ? (
this.loading()
) : (
<>
{this.body() !== undefined && <div className={body}>{this.body()}</div>}
{this.footer() !== undefined && (
<div className={mergeStyles(classNames.footer, footer)}>{this.footer()}</div>
)}
</>
)}
</div>
);
}
protected async getData(): Promise<S> {
return undefined;
}
protected header(): JSX.Element | undefined {
return undefined;
}
protected body(): JSX.Element | undefined {
return undefined;
}
protected footer(): JSX.Element | undefined {
return undefined;
}
protected loading(): JSX.Element | undefined {
return undefined;
}
protected styling(): IWidgetClassNames {
return {};
}
}
Ниже приведены рекомендуемые методы для переопределения.
Методы | Функция | Рекомендуется переопределить |
---|---|---|
constructor() |
Вызывает инициал this.state и вызывает конструктор суперкласса React.Component . |
Нет |
componentDidMount() |
Вызывается после подключения компонента и присваивает значение свойству data состояния путем вызова getData() метода . |
Нет |
render() |
Вызывается при обновлении. В этом методе определен макет панели мониторинга по умолчанию. | Нет |
getData() |
Вызывает данные, необходимые мини-приложению. Значение, возвращаемое этим методом, имеет значение this.state.data . |
Да |
header() |
Вызывает заголовок мини-приложения. Вы можете переопределить этот метод, чтобы настроить мини-приложение или нет. В противном случае у мини-приложения не будет заголовка. | Да |
body() |
Вызывает текст мини-приложения. Вы можете переопределить этот метод, чтобы настроить мини-приложение или нет. В противном случае у мини-приложения не будет текста. | Да |
footer() |
Вызывает то, как выглядит нижний колонтитул мини-приложения. Вы можете переопределить этот метод, чтобы настроить мини-приложение или нет. В противном случае мини-приложение не будет иметь нижний колонтитул. | Да |
loading() |
Вызывается, когда мини-приложение находится в процессе получения данных. Если требуется индикатор загрузки, метод может вернуть JSX.Element объект , содержащий необходимые компоненты для отрисовки индикатора загрузки. |
Да |
style() |
Вызывает объект , определяющий имена классов для различных частей мини-приложения. | Да |
Набор средств Microsoft Graph в качестве содержимого мини-приложения
Набор средств Microsoft Graph — это набор возобновляемых веб-компонентов, не зависящих от платформы, который помогает получить доступ к Microsoft Graph и работать с ним. Набор средств Microsoft Graph можно использовать с любой веб-платформой или без нее.
Чтобы использовать Microsoft Graph Toolkit в качестве содержимого мини-приложения, выполните следующие действия.
Добавление функции единого входа в приложение Teams. Microsoft Teams предоставляет функцию единого входа (SSO) для приложения, чтобы получить маркер пользователя, вошедшего в Teams, для доступа к Microsoft Graph. Дополнительные сведения см. в статье Единый вход в приложение Teams.
Установите необходимые
npm
пакеты.Выполните следующую команду в папке проекта
tabs
, чтобы установить необходимыеnpm
пакеты:npm install @microsoft/mgt-react @microsoft/mgt-teamsfx-provider
Добавление нового мини-приложения Graph Toolkit. Создайте файл мини-приложения в папке проекта
src/views/widgets
, напримерGraphWidget.tsx
. В этом мини-приложении пользователи помогут предоставить нашему приложению доступ к Microsoft Graph, а затем отобразим список задач пользователя с помощью Microsoft Graph Toolkit.Следующий код является примером использования компонента Todo из Microsoft Graph Toolkit в мини-приложении:
import { Providers, ProviderState, Todo } from "@microsoft/mgt-react"; import { TeamsFxProvider } from "@microsoft/mgt-teamsfx-provider"; import { loginAction } from "../../internal/login"; import { TeamsUserCredentialContext } from "../../internal/singletonContext"; import { BaseWidget } from "@microsoft/teamsfx-react"; interface IGraphWidgetState { needLogin: boolean; } export class GraphWidget extends Widget<any, IGraphWidgetState> { override body(): JSX.Element | undefined { return <div>{this.state.needLogin === false && <Todo />}</div>; } async componentDidMount() { super.componentDidMount(); // Initialize TeamsFx provider const provider = new TeamsFxProvider(TeamsUserCredentialContext.getInstance().getCredential(), [ "Tasks.ReadWrite", ]); Providers.globalProvider = provider; // Check if user is signed in if (await this.checkIsConsentNeeded()) { await loginAction(["Tasks.ReadWrite"]); } // Update signed in state Providers.globalProvider.setState(ProviderState.SignedIn); this.setState({ needLogin: false }); } /** * Check if user needs to consent * @returns true if user needs to consent */ async checkIsConsentNeeded() { let needConsent = false; try { await TeamsUserCredentialContext.getInstance().getCredential().getToken(["Tasks.ReadWrite"]); } catch (error) { needConsent = true; } return needConsent; } }
В мини-приложении можно использовать альтернативные компоненты Microsoft Graph Toolkit. Дополнительные сведения см. в разделе Microsoft Graph Toolkit.
Добавьте мини-приложение в макет панели мониторинга. Добавьте новое мини-приложение в файл панели мониторинга.
... export default class YourDashboard extends BaseDashboard<any, any> { ... override layout(): undefined | JSX.Element { return ( <> <GraphWiget /> </> ); } ... }
Теперь, запустите или обновите приложение Teams, вы увидите новое мини-приложение с помощью Microsoft Graph Toolkit.
API Graph вызов
Microsoft API Graph — это веб-API, который можно использовать для взаимодействия с облаком Майкрософт и другими службами. Пользовательские приложения могут использовать API Microsoft Graph для подключения к данным и повышения производительности организации.
Перед реализацией логики вызова API Graph необходимо включить единый вход для проекта панели мониторинга. Дополнительные сведения см. в статье Добавление единого входа в приложение Teams.
Чтобы добавить API Graph вызов:
- Вызов API Graph из внешнего интерфейса (используйте делегированные разрешения)
- Вызов API Graph из серверной части (использование разрешений приложения)
Вызов API Graph из внешнего интерфейса (используйте делегированные разрешения)
Если вы хотите вызвать API Graph с вкладки внешнего интерфейса, выполните следующие действия.
Чтобы получить имя область разрешений, связанного с API Graph, которую вы планируете вызвать, см. API Graph.
Создайте клиент Graph, добавив область, связанный с API Graph, который требуется вызвать.
let credential: TeamsUserCredential; credential = TeamsUserCredentialContext.getInstance().getCredential(); const graphClient: Client = createMicrosoftGraphClientWithCredential(credential, scope);
Вызовите API Graph и выполните анализ ответа в определенной модели.
try { const graphApiResult = await graphClient.api("<GRAPH_API_PATH>").get(); // Parse the graphApiResult into a Model you defined, used by the front-end. } catch (e) {}
Вызов API Graph из серверной части (использование разрешений приложения)
Если вы хотите вызвать API Graph из внутренней части, выполните следующие действия.
- Разрешения приложения согласия
- Добавление функции Azure
- Добавление логики в функцию Azure
- Вызов функции Azure из внешнего интерфейса
Разрешения приложения согласия
Чтобы предоставить разрешения приложения, выполните следующие действия.
- Перейдите к портал Azure.
- Выберите Microsoft Entra ID.
- Выберите Регистрация приложений в левой области.
- Выберите приложение панели мониторинга.
- Выберите Разрешения API в области слева.
- Выберите Добавить разрешение.
- Выберите Microsoft Graph.
- Выберите Разрешения приложения.
- Найдите необходимые разрешения.
- Нажмите кнопку Добавить разрешения внизу.
- Выберите ✔Предоставить согласие администратора.
- Нажмите кнопку Да , чтобы завершить согласие администратора.
Добавление функции Azure
В левой области Visual Studio Code выберите Teams Toolkit>Добавление функций>Функции Azure и введите имя функции.
Дополнительные сведения о добавлении функции Azure в проект см. в статье Интеграция Функции Azure с приложением Teams.
Добавление логики в функцию Azure
В папке index.ts
/index.ts
с именем Функция Azure можно добавить логику, содержащую серверную API Graph вызов с разрешениями приложения. См. следующий фрагмент кода:
/**
* This function handles requests from teamsfx client.
* The HTTP request should contain an SSO token queried from Teams in the header.
* Before triggering this function, teamsfx binding would process the SSO token and generate teamsfx configuration.
*
* You should initializes the teamsfx SDK with the configuration and calls these APIs.
*
* The response contains multiple message blocks constructed into a JSON object, including:
* - An echo of the request body.
* - The display name encoded in the SSO token.
* - Current user's Microsoft 365 profile if the user has consented.
*
* @param {Context} context - The Azure Functions context object.
* @param {HttpRequest} req - The HTTP request.
* @param {teamsfxContext} TeamsfxContext - The context generated by teamsfx binding.
*/
export default async function run(
context: Context,
req: HttpRequest,
teamsfxContext: TeamsfxContext
): Promise<Response> {
context.log("HTTP trigger function processed a request.");
// Initialize response.
const res: Response = {
status: 200,
body: {},
};
// Your logic here.
return res;
}
Вызов функции Azure из внешнего интерфейса
Вызовите функцию Azure по имени функции. Чтобы вызвать функцию Azure, ознакомьтесь со следующим фрагментом кода:
const functionName = process.env.REACT_APP_FUNC_NAME || "myFunc";
export let taskName: string;
export async function callFunction(params?: string) {
taskName = params || "";
const credential = TeamsUserCredentialContext.getInstance().getCredential();
if (!credential) {
throw new Error("TeamsFx SDK is not initialized.");
}
try {
const apiBaseUrl = process.env.REACT_APP_FUNC_ENDPOINT + "/api/";
const apiClient = createApiClient(
apiBaseUrl,
new BearerTokenAuthProvider(async () => (await credential.getToken(""))!.token)
);
const response = await apiClient.get(functionName);
return response.data;
} catch (err: unknown) {
...
}
}
Дополнительные сведения см. в разделе:
Внедрение Power BI на панель мониторинга
Сведения о внедрении Power BI на панель мониторинга см. в статье Реагирование клиента Power BI.
Пошаговые инструкции
Выполните пошаговые инструкции по созданию панели мониторинга и узнайте, как добавить мини-приложение и API Graph вызов на панель мониторинга.
См. также
Platform Docs