跳转至

useTasks reference(useTasks 参考文档)

Learn more about the useTasks hook.

/*
 * Copyright 2025 Palantir Technologies, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import useSWR from "swr";
import { useOsdkClient } from "@osdk/react";
import { OsdkITask } from "@advanced-to-do-application/sdk";
import { IProject } from "./useProjects";
import { useCallback, useEffect, useState } from "react";
import useAdmin from "./useAdmin";
import _ from "lodash";
import type { User } from "@osdk/foundry.admin";
import type { InterfaceMetadata } from "@osdk/api";

export interface ITask {
    osdkTask: OsdkITask.OsdkInstance;
    createdBy: User;
    assignedTo: User;
}

function useTasks(project: IProject) {
    const client = useOsdkClient();
    const [metadata, setMetadata] = useState<InterfaceMetadata>();
    const { getBatchUserDetails } = useAdmin();
    // `$includeAllBaseObjectProperties: true,` means that although we are fetching the object through its interface implementation,
    // we are still going to get all the base object properties; when we pivot to the base object using $as, we don not need to fetch them again.
    const fetcher = useCallback(async () => {
        const tasksPage = await client(OsdkITask).where({
            projectId: { $eq: project.$primaryKey },
        }).fetchPage({
            $includeAllBaseObjectProperties: true,
            $orderBy: { "dueDate": "desc", "status": "asc" },
        });
        // Get the user details for the createdBy field.
        const createdByIds = _.uniq(tasksPage.data.map((task) => task.createdBy as string));
        const createdByUserList = await getBatchUserDetails(createdByIds);
        // Get the user details for the assignedTo field.
        const assignedToIds = _.uniq(tasksPage.data.map((task) => task.assignedTo as string));
        const assignedToUserList = await getBatchUserDetails(assignedToIds);
        const tasksList: ITask[] = tasksPage.data.map((task) => ({
            osdkTask: task,
            assignedTo: assignedToUserList[task.assignedTo as string],
            createdBy: createdByUserList[task.createdBy as string],
            }));
      return tasksList;
    } , [getBatchUserDetails, project.$primaryKey, client]);

  const { data, isLoading, isValidating, error, mutate } = useSWR<ITask[]>(
    ["tasks",project.$primaryKey],
    fetcher,
    { revalidateOnFocus: false }
  );

  // This shows how we read the object type metadata and use the property display name from the ontology.
  const getObjectTypeMetadata = useCallback(async () => {
    const objectTypeMetadata = await client.fetchMetadata(OsdkITask);
    setMetadata(objectTypeMetadata);
    } , [client]);

    useEffect(() => {
        getObjectTypeMetadata();
    }, [getObjectTypeMetadata]);


    useEffect(() => {
        // Subscribe to the object set to get real-time updates.
        const subscription = client(OsdkITask)
            .where({
                projectId: { $eq: project.$primaryKey },
            })
            .subscribe(
                {
                    onChange(update) {
                        if (update.state === "ADDED_OR_UPDATED") {
                            // An object has received an update or an object was added to the object set.
                            const currentObject = data?.find((task) => task.osdkTask.$primaryKey === update.object.$primaryKey);
                            if (currentObject !== undefined) {
                                // Get the user details for the createdBy field and the assignedTo field.
                                getBatchUserDetails([update.object.createdBy as string, update.object.assignedTo as string]).then((userList) => {
                                    const updatedObject: ITask = {
                                        osdkTask: update.object,
                                        assignedTo: userList[update.object.assignedTo as string],
                                        createdBy: userList[update.object.createdBy as string],
                                    };
                                    // Replace the object in date with the new one to mutate without fetching.
                                    mutate((currentData: ITask[] | undefined) => {
                                        if (!currentData) return [];
                                        return currentData.map((task) => task.osdkTask.$primaryKey === update.object.$primaryKey ? updatedObject : task);
                                    }, { revalidate: false });
                                });
                            }
                        }
                        else if (update.state === "REMOVED") {
                            // remove the object from the data mutate without fetching.
                            mutate((currentData: ITask[] | undefined) => {
                                if (!currentData) return [];
                                return currentData.filter((task) => task.osdkTask.$primaryKey !== update.object.$primaryKey);
                            }, { revalidate: false });
                        }
                    },
                    onSuccessfulSubscription() {
                        // The subscription was successful and you can expect to receive updates.
                    },
                    onError(err) {
                        // There was an error with the subscription and you will not receive any more updates.
                        console.error(err);
                    },
                    onOutOfDate() {
                        // We could not keep track of all changes. Reload the objects in your set.
                    },
                },
            );

        subscription.unsubscribe();
    },[data, getBatchUserDetails, mutate, project.$primaryKey, client]);

  return {
    tasks: data ?? [],
    isLoading,
    isValidating,
    isError: error,
    metadata,
  };
}

export default useTasks;

中文翻译

useTasks 参考文档

了解更多关于 useTasks hook 的信息。

/*
 * 版权所有 2025 Palantir Technologies, Inc. 保留所有权利。
 *
 * 根据 Apache 许可证 2.0 版("许可证")授权;
 * 除非遵守许可证,否则您不得使用此文件。
 * 您可以在以下网址获取许可证副本:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 除非适用法律要求或书面同意,否则按"原样"分发的软件
 * 不提供任何明示或暗示的保证或条件。
 * 请参阅许可证以了解管理权限和限制的具体语言。
 */

import useSWR from "swr";
import { useOsdkClient } from "@osdk/react";
import { OsdkITask } from "@advanced-to-do-application/sdk";
import { IProject } from "./useProjects";
import { useCallback, useEffect, useState } from "react";
import useAdmin from "./useAdmin";
import _ from "lodash";
import type { User } from "@osdk/foundry.admin";
import type { InterfaceMetadata } from "@osdk/api";

export interface ITask {
    osdkTask: OsdkITask.OsdkInstance;
    createdBy: User;
    assignedTo: User;
}

function useTasks(project: IProject) {
    const client = useOsdkClient();
    const [metadata, setMetadata] = useState<InterfaceMetadata>();
    const { getBatchUserDetails } = useAdmin();
    // `$includeAllBaseObjectProperties: true` 表示虽然我们通过接口实现获取对象,
    // 但仍然会获取所有基础对象属性;当我们使用 $as 切换到基础对象时,无需再次获取这些属性。
    const fetcher = useCallback(async () => {
        const tasksPage = await client(OsdkITask).where({
            projectId: { $eq: project.$primaryKey },
        }).fetchPage({
            $includeAllBaseObjectProperties: true,
            $orderBy: { "dueDate": "desc", "status": "asc" },
        });
        // 获取 createdBy 字段的用户详情。
        const createdByIds = _.uniq(tasksPage.data.map((task) => task.createdBy as string));
        const createdByUserList = await getBatchUserDetails(createdByIds);
        // 获取 assignedTo 字段的用户详情。
        const assignedToIds = _.uniq(tasksPage.data.map((task) => task.assignedTo as string));
        const assignedToUserList = await getBatchUserDetails(assignedToIds);
        const tasksList: ITask[] = tasksPage.data.map((task) => ({
            osdkTask: task,
            assignedTo: assignedToUserList[task.assignedTo as string],
            createdBy: createdByUserList[task.createdBy as string],
            }));
      return tasksList;
    } , [getBatchUserDetails, project.$primaryKey, client]);

  const { data, isLoading, isValidating, error, mutate } = useSWR<ITask[]>(
    ["tasks",project.$primaryKey],
    fetcher,
    { revalidateOnFocus: false }
  );

  // 这展示了如何读取对象类型元数据(object type metadata)并使用本体(ontology)中的属性显示名称。
  const getObjectTypeMetadata = useCallback(async () => {
    const objectTypeMetadata = await client.fetchMetadata(OsdkITask);
    setMetadata(objectTypeMetadata);
    } , [client]);

    useEffect(() => {
        getObjectTypeMetadata();
    }, [getObjectTypeMetadata]);


    useEffect(() => {
        // 订阅对象集以获取实时更新。
        const subscription = client(OsdkITask)
            .where({
                projectId: { $eq: project.$primaryKey },
            })
            .subscribe(
                {
                    onChange(update) {
                        if (update.state === "ADDED_OR_UPDATED") {
                            // 对象收到更新或对象被添加到对象集中。
                            const currentObject = data?.find((task) => task.osdkTask.$primaryKey === update.object.$primaryKey);
                            if (currentObject !== undefined) {
                                // 获取 createdBy 字段和 assignedTo 字段的用户详情。
                                getBatchUserDetails([update.object.createdBy as string, update.object.assignedTo as string]).then((userList) => {
                                    const updatedObject: ITask = {
                                        osdkTask: update.object,
                                        assignedTo: userList[update.object.assignedTo as string],
                                        createdBy: userList[update.object.createdBy as string],
                                    };
                                    // 替换 data 中的对象,无需重新获取即可进行突变(mutate)。
                                    mutate((currentData: ITask[] | undefined) => {
                                        if (!currentData) return [];
                                        return currentData.map((task) => task.osdkTask.$primaryKey === update.object.$primaryKey ? updatedObject : task);
                                    }, { revalidate: false });
                                });
                            }
                        }
                        else if (update.state === "REMOVED") {
                            // 从 data 中移除对象,无需重新获取即可进行突变。
                            mutate((currentData: ITask[] | undefined) => {
                                if (!currentData) return [];
                                return currentData.filter((task) => task.osdkTask.$primaryKey !== update.object.$primaryKey);
                            }, { revalidate: false });
                        }
                    },
                    onSuccessfulSubscription() {
                        // 订阅成功,您可以期待收到更新。
                    },
                    onError(err) {
                        // 订阅出现错误,您将不再收到任何更新。
                        console.error(err);
                    },
                    onOutOfDate() {
                        // 无法跟踪所有更改。请重新加载集合中的对象。
                    },
                },
            );

        subscription.unsubscribe();
    },[data, getBatchUserDetails, mutate, project.$primaryKey, client]);

  return {
    tasks: data ?? [],
    isLoading,
    isValidating,
    isError: error,
    metadata,
  };
}

export default useTasks;