循序渐进 · 教学 · 函数(十四)

用函数配置通知

函数可以灵活决定通知发给谁、发什么内容,甚至发到用户外部邮箱。这篇讲自定义通知、获取用户与组、以及返回收件人。

全部目录 ← 上一篇 用函数配置通知 下一篇 →
本文来源 · Source 内容整理自 Palantir Foundry 官方文档:
https://www.palantir.com/docs/foundry/functions/configure-notifications/
原始标题:Language-agnostic features > Configure notifications

先记住这几条

① 函数决定通知内容与收件人
比静态配置的通知更灵活,可以运行时算出来。
② 可以发到外部邮箱
通知不只站内,还能发到用户邮箱地址。
③ 收件人要从本体里取
通常需要先查到 User / Group 对象,再作为收件人返回。
0

写在前面

函数可以用来灵活地配置平台里要发出的通知,包括发到用户外部邮箱的通知。

在函数里配置通知会用到 Principal(代表一个 UserGroup)和 notification 类型。读这一节时,下面两个参考可能会有用:

1

定义自定义通知

定义自定义通知

要点:通知的内容结构怎么定义。

假设本体里有一个 Issue 对象,可以指派给某个 User。你可以写一个函数,定义要发给这个 User 的通知,内容带上该 Issue 的详细信息。

import { EmailNotificationContent, Function, Notification, ShortNotification, User } from "@foundry/functions-api";
import { Issue } from "@foundry/ontology-api";

export class NotificationFunctions {
    @Function()
    public createIssueNotification(issue: Issue, user: User): Notification {
        // 创建一条站内展示的短通知
        const shortNotification = ShortNotification.builder()
            .heading("New issue")
            .content("A new issue has been assigned to you.")
            // 链到平台里的 Issue 对象
            .addObjectLink("Issue", issue)
            .build();

        // 定义邮件正文。邮件正文可以包含无样式的 HTML,比如数据表格
        // 注意:正文里可以同时取用 user 和 issue 的属性
        const emailBody = `Hello, ${user.firstName},

A new issue has been assigned to you: ${issue.description}.`;

        const emailNotificationContent = EmailNotificationContent.builder()
            .subject("New issue")
            .body(emailBody)
            .addObjectLink("Issue", issue)
            .build();

        return Notification.builder()
            .shortNotification(shortNotification)
            .emailNotificationContent(emailNotificationContent)
            .build();
    }
}
import { NotificationLink, Notification } from "@osdk/functions";
import { Issue } from "@ontology/sdk";
import type { Osdk } from "@osdk/api";

export default function createIssueNotification(issue: Osdk.Instance<Issue>): Notification {
    // 链到平台里的 Issue 对象
    const links: NotificationLink[] = [
        {
            label: "Issue",
            linkTarget: {
                type: "object",
                object: issue
            }
        }
    ]

    const platformNotification = {
        heading: "New issue",
        content: "A new issue has been assigned to you.",
        links: links
    }

    // 定义邮件正文。邮件正文可以包含无样式的 HTML,比如数据表格
    const emailBody = `Hello,

A new issue has been assigned to you: ${issue.description}.`;

    const emailNotification = {
        subject: "New issue",
        body: emailBody,
        links: links
    }

    return {
        platformNotification: platformNotification,
        emailNotification: emailNotification
    }
}
from functions.api import function, Notification, PlatformNotification, NotificationObjectLink, EmailNotification
from ontology_sdk.ontology.objects import Issue

@function()
def createIssueNotification(issue: Issue) -> Notification[Issue]:
# 如果要配置带对象链接的通知,必须在返回类型里声明对象类型

    # 链到平台里的 Issue 对象
    links = [
        NotificationObjectLink(label="Issue", objectTarget=issue)
    ]

    #创建一条站内展示的短通知
    platform_notification = PlatformNotification(
        heading="New issue",
        content="A new issue has been assigned to you.",
        links=links
    )

    # 定义邮件正文。邮件正文可以包含无样式的 HTML,比如数据表格
    emailBody = f"Hello, \n A new issue has been assigned to you: {issue.description}."

    email_notification = EmailNotification(
            subject="New issue",
            body=emailBody,
            links=links
        )

    return Notification(platform_notification, email_notification)
2

获取用户与组

获取用户与组

要点:从本体里查出要通知的对象。

除了把 User 作为参数传进函数,你也可以按需去查一个 UserGroup。假设 Issue 对象有一个 assignee 字段,里面存的是用户 ID。下面这个例子中,函数返回一条提醒用户关注该 issue 的通知:

import { EmailNotificationContent, Function, Notification, ShortNotification, User, UserFacingError, Users } from "@foundry/functions-api";
import { Issue } from "@foundry/ontology-api";

export class NotificationFunctions {
    @Function()
    public async createIssueReminderNotification(issue: Issue): Promise<Notification> {
        if (!issue.assignee) {
            throw new UserFacingError("Cannot create notification for issue without an assignee.");
        }

        const user = await Users.getUserByIdAsync(issue.assignee);

        const emailBody = `Hello, ${user.firstName},

This is a reminder to investigate the following issue: ${issue.description}`;

        // 也可以用这种结构把整条通知一次内联构造出来
        return Notification.builder()
            .shortNotification(ShortNotification.builder()
                .heading("Issue reminder")
                .content("Investigate this issue.")
                .addObjectLink("Issue", issue)
                .build())
            .emailNotificationContent(EmailNotificationContent.builder()
                .subject("New issue")
                .body(emailBody)
                .addObjectLink("Issue", issue)
                .build())
            .build();
    }
}
import { NotificationLink, Notification } from "@osdk/functions";
import { Users } from "@osdk/foundry.admin";
import { Issue } from "@ontology/sdk";
import { Client } from "@osdk/client";
import type { Osdk } from "@osdk/api";

export default async function createIssueReminderNotification(client: Client, issue: Osdk.Instance<Issue>): Promise<Notification> {
    const user = await Users.get(client, issue.assignee);

    const emailBody = `Hello, ${user.firstName},

This is a reminder to investigate the following issue: ${issue.description}`;

    // 也可以用这种结构把整条通知一次内联构造出来
    const links: NotificationLink[] = [
        {
            label: "Issue",
            linkTarget: {
                type: "object",
                object: issue
            }
        }
    ]

    // 也可以用这种结构把整条通知一次内联构造出来
    return {
        platformNotification: {
            heading: "Issue reminder",
            content: "Investigate this issue.",
            links:  links
        },
        emailNotification: {
            subject: "New issue",
            body: emailBody,
            links: links
        }
    }
}
from functions.api import function, Notification, PlatformNotification, NotificationObjectLink, EmailNotification
from ontology_sdk.ontology.objects import Issue
from foundry_sdk import FoundryClient
import foundry_sdk

@function()
def createIssueReminderNotification(issue: Issue) -> Notification[Issue]:
    client = FoundryClient(auth=foundry_sdk.UserTokenAuth(...), hostname="example.palantirfoundry.com")

    user = client.admin.User.get(issue.assignee)

    # 链到平台里的 Issue 对象
    links = [
        NotificationObjectLink(label="Issue", objectTarget=issue)
    ]

    #创建一条站内展示的短通知
    platform_notification = PlatformNotification(
        heading="Issue reminder",
        content="Investigate this issue.",
        links=links
    )

    # 定义邮件正文。邮件正文可以包含无样式的 HTML,比如数据表格
    # 注意:正文里可以同时取用 user 和 issue 的属性
    emailBody = f"Hello, {user.firstName}, \n A new issue has been assigned to you: {issue.description}."

    email_notification = EmailNotification(
            subject="Issue reminder",
            body=emailBody,
            links=links
        )

    return Notification(platform_notification, email_notification)
3

返回收件人

返回收件人

要点:把查到的用户/组作为收件人返回给平台。

上面介绍的 Notification API 让你返回自定义的通知内容。用函数配置通知还有另一种方式:返回通知的收件人列表。做法很简单 —— 写一个函数,返回一个或多个 Principal 对象,比如 UserGroup 对象。

下面这个例子中,函数同时返回了报告该 issue 的用户和当前负责该 issue 的用户:

import { Function, User, UserFacingError, Users } from "@foundry/functions-api";
import { Issue } from "@foundry/ontology-api";

export class NotificationFunctions {
    /**
     * 给定一个 Issue,返回代表该 Issue 当前负责人和最初报告人的用户。
     */
    @Function()
    public async getIssueAssigneeAndReporter(issue: Issue): Promise<User[]> {
        if (!issue.assignee || !issue.reporter) {
            throw new UserFacingError("Cannot create notification for issue without an assignee or reporter.");
        }

        const user = await Users.getUserByIdAsync(issue.assignee);
        const issueReporter = await Users.getUserByIdAsync(issue.reporter);

        return [user, issueReporter];
    }
}
import { UserId, Principal } from "@osdk/functions";
import { Users, Groups } from "@osdk/foundry.admin";
import { Issue } from "@ontology/sdk";
import { Client } from "@osdk/client";
import type { Osdk } from "@osdk/api";

/**
 * 给定一个 Issue,返回代表该 Issue 当前负责人和最初报告人的用户。
 */
async function getIssueAssigneeAndReporter(client: Client, issue: Osdk.Instance<Issue>): Promise<UserId[]> {
    const user = await Users.get(client, issue.assignee);
    const issueReporter = await Users.get(client, issue.reporter);

    return [user.id, issueReporter.id];
}

/**
 * 给定一个 Issue,返回该 issue 当前的负责人用户,以及该 issue 所属的组。
 */
async function getIssueAssigneeAndGroups(client: Client, issue: Osdk.Instance<Issue>): Promise<Principal[]> {
    // 要同时返回组和用户,就用 Principal 类型。

    const user = await Users.get(client, issue.assignee);
    const group = await Groups.get(client, issue.group);

    return [{type: "user", id: user.id}, {type: "group", id: group.id}];
}
from functions.api import Array, function, Principal, UserId
from ontology_sdk.ontology.objects import Issue
from foundry_sdk import FoundryClient
import foundry_sdk

# 给定一个 Issue,返回代表该 Issue 当前负责人和最初报告人的用户。
@function()
def getIssueAssigneeAndReporter(issue: Issue) -> Array[UserId]:
    client = FoundryClient(auth=foundry_sdk.UserTokenAuth(...), hostname="example.palantirfoundry.com")

    user = client.admin.User.get(issue.assignee)
    issueReporter = client.admin.User.get(issue.reporter)

    return [user.id, issueReporter.id]

# 给定一个 Issue,返回该 issue 当前的负责人用户,以及该 issue 所属的组。
@function()
def getIssueAssigneeAndGroup(issue: Issue) -> Array[Principal]:
    # 要同时返回组和用户,就用 Principal 类型。
    client = FoundryClient(auth=foundry_sdk.UserTokenAuth(...), hostname="example.palantirfoundry.com")

    user = client.admin.User.get(issue.assignee)
    group = client.admin.Group.get(issue.group)

    return [Principal.user(user.id), Principal.group(group.id)]

延伸阅读 · 相关页面

按主题横向跳转,不必顺着目录一篇篇读。

常见问题速答 · FAQ

关于「用函数配置通知」,读者最常问的几个问题。

定义自定义通知是什么?
通知的内容结构怎么定义。假设本体里有一个 Issue 对象,可以指派给某个 User。你可以写一个函数,定义要发给这个 User 的通知,内容带上该 Issue 的详细信息。
获取用户与组是什么?
从本体里查出要通知的对象。除了把 User 作为参数传进函数,你也可以按需去查一个 User 或 Group。假设 Issue 对象有一个 assignee 字段,里面存的是用户 ID。下面这个例子中,函数返回一条提醒用户关注该 issue 的通知。
返回收件人是什么?
把查到的用户/组作为收件人返回给平台。上面介绍的 Notification API 让你返回自定义的通知内容。用函数配置通知还有另一种方式:返回通知的收件人列表。