> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirurobotics.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Groups

export const GroupManagerBadge = ({size = "md"}) => {
  return <Tooltip tip="Members who are managers of a group that contains this resource can execute this action." cta="Workspace roles" href="/admin/users/access-control">
            <Badge icon="group" color="blue" size={size}>group manager</Badge>
        </Tooltip>;
};

export const AdminBadge = ({size = "md"}) => {
  return <Tooltip tip="Workspace owners and administrators can execute this action." cta="Workspace roles" href="/admin/users/access-control">
            <Badge icon="shield-check" color="blue" size={size}>admin</Badge>
        </Tooltip>;
};

export const Framed = ({image, background, link, alt = "Framed content", borderWidth = "24px", outerRadius = "10px", innerRadius = "6px"}) => {
  const parseShorthand = value => {
    const values = String(value).trim().split(/\s+/);
    switch (values.length) {
      case 1:
        return [values[0], values[0], values[0], values[0]];
      case 2:
        return [values[0], values[1], values[0], values[1]];
      case 3:
        return [values[0], values[1], values[2], values[1]];
      default:
        return values.slice(0, 4);
    }
  };
  const isZero = v => parseFloat(v) === 0;
  const padding = parseShorthand(borderWidth);
  const outer = parseShorthand(outerRadius);
  const cornerMasks = [];
  if (isZero(padding[0]) && isZero(padding[3])) {
    cornerMasks.push(`radial-gradient(circle at 0% 0%, transparent ${outer[0]}, black ${outer[0]})`);
  }
  if (isZero(padding[0]) && isZero(padding[1])) {
    cornerMasks.push(`radial-gradient(circle at 100% 0%, transparent ${outer[1]}, black ${outer[1]})`);
  }
  if (isZero(padding[2]) && isZero(padding[1])) {
    cornerMasks.push(`radial-gradient(circle at 100% 100%, transparent ${outer[2]}, black ${outer[2]})`);
  }
  if (isZero(padding[2]) && isZero(padding[3])) {
    cornerMasks.push(`radial-gradient(circle at 0% 100%, transparent ${outer[3]}, black ${outer[3]})`);
  }
  const backgroundMask = cornerMasks.length > 0 ? cornerMasks.join(", ") : undefined;
  const innerImage = <img src={image} alt={alt} noZoom={link ? true : false} style={{
    display: "block",
    width: "100%",
    margin: 0,
    borderRadius: 0
  }} />;
  return <div style={{
    display: "inline-block",
    position: "relative",
    borderRadius: outerRadius,
    overflow: "hidden"
  }}>
            {}
            {background && <div style={{
    position: "absolute",
    inset: 0,
    backgroundImage: `url(${background})`,
    backgroundSize: "cover",
    maskImage: backgroundMask,
    WebkitMaskImage: backgroundMask,
    maskComposite: "intersect",
    WebkitMaskComposite: "source-in"
  }} />}
            {}
            <div style={{
    position: "relative",
    padding: borderWidth
  }}>
                <div style={{
    borderRadius: innerRadius,
    overflow: "hidden",
    lineHeight: 0
  }}>
                    {link ? <a href={link}>{innerImage}</a> : innerImage}
                </div>
            </div>
        </div>;
};

export const NullableBadge = ({size = "sm"}) => {
  return <Tooltip tip="Property does not need to be set">
            <Badge icon="circle" color="gray" size={size}>nullable</Badge>
        </Tooltip>;
};

export const MutableBadge = ({size = "sm"}) => {
  return <Tooltip tip="Property is automatically updated by the system; cannot be modified directly">
            <Badge icon="feather" color="orange" size={size}>mutable</Badge>
        </Tooltip>;
};

export const EditableBadge = ({size = "sm"}) => {
  return <Tooltip tip="Property can be directly modified">
            <Badge icon="pencil" color="blue" size={size}>editable</Badge>
        </Tooltip>;
};

<Framed background="https://assets.mirurobotics.com/docs/v04/images/groups/background.jpeg" image="https://assets.mirurobotics.com/docs/v04/images/groups/header:page.png" borderWidth={"24px 0 0 36px"} innerRadius={"8px 0 0 0"} />

A **group** is a hierarchical organizational unit for devices, allowing you to organize devices into a logical tree structure.

Groups can contain both devices and subgroups. Devices may be assigned to at most one group, or be unassigned to any group.

## Properties

<ParamField path="name" type="string">
  <EditableBadge />

  A human-readable display name for the group. Must be unique within the workspace.

  Examples: `Production`, `Warehouse Floor 2`, `Europe`
</ParamField>

<ParamField path="parent" type="Group">
  <EditableBadge />

  {' '}

  <NullableBadge />

  The parent group in the hierarchy. Set to `null` for top-level groups; set to another group's ID to nest this group as a child group.

  Examples: `grp_123`, `null`
</ParamField>

<ParamField path="devices" type="[]Device">
  <MutableBadge />

  The devices assigned to this group. Computed by the server—useful for determining whether to display device-related affordances in the UI.
</ParamField>

<ParamField path="subgroups" type="[]Group">
  <MutableBadge />

  The child subgroups within this group. Computed by the server—useful for rendering expand/collapse indicators in a tree view.
</ParamField>

## Structure

Groups organize devices into a tree hierarchy. A workspace can have multiple top-level groups, and each group can contain subgroups.

<Tree.Folder name="Workspace" defaultOpen>
  <Tree.Folder name="Production" defaultOpen>
    <Tree.Folder name="North America" defaultOpen>
      <Tree.File name="Device A" />

      <Tree.File name="Device B" />
    </Tree.Folder>

    <Tree.Folder name="Europe" defaultOpen>
      <Tree.File name="Device C" />
    </Tree.Folder>
  </Tree.Folder>

  <Tree.Folder name="Staging" defaultOpen>
    <Tree.File name="Device D" />
  </Tree.Folder>

  <Tree.File name="Device E (unassigned)" />
</Tree.Folder>

Devices belong to at most one group. Devices that haven't been assigned to any group remain ungrouped at the workspace level.

## Create a group  <AdminBadge />  <GroupManagerBadge />

Go to the [Groups page](https://app.mirurobotics.com/groups) and navigate into the group you want to create a group inside of. Click the **+ Group** button in the top right corner.

<Frame>
  ![Group Page](https://assets.mirurobotics.com/docs/v04/images/groups/page.png)
</Frame>

Fill in the fields, then click **Create**.

<Frame>
  ![Create Group Dialog](https://assets.mirurobotics.com/docs/v04/images/groups/create-dialog.png)
</Frame>

## Edit a group  <AdminBadge />  <GroupManagerBadge />

Navigate to the [Groups page](https://assets.mirurobotics.com/docs/v04/images/groups/page.png), click the ellipses (...) on the group you want to edit, and hit **Edit**.

<Frame>
  ![Group Ellipses Dropdown](https://assets.mirurobotics.com/docs/v04/images/groups/ellipses-dropdown.png)
</Frame>

Update the desired fields, then click **Save**.

<Frame>
  ![Edit Group Dialog](https://assets.mirurobotics.com/docs/v04/images/groups/edit-dialog.png)
</Frame>

## Move a device  <AdminBadge />  <GroupManagerBadge />

To move a device to a different group, click the ellipses (...) on the device you want to move and select **Move**.

<Frame>
  ![Device Ellipses Dropdown](https://assets.mirurobotics.com/docs/v04/images/groups/device-ellipses-dropdown.png)
</Frame>

A dialog will appear—select the group you want to move the device to and hit **Move**.

<Frame>
  ![Move Device Dialog](https://assets.mirurobotics.com/docs/v04/images/groups/move-device-dialog.png)
</Frame>

## Delete a group  <AdminBadge />  <GroupManagerBadge />

A group can only be deleted if it has no subgroups and no assigned devices. If you need to delete a group that still contains devices or subgroups, first move or reassign its contents.

To delete a group, click the ellipses (...) on the group you want to delete and select **Delete**.

<Frame>
  ![Group Ellipses Dropdown](https://assets.mirurobotics.com/docs/v04/images/groups/ellipses-dropdown.png)
</Frame>

A confirmation dialog will appear. Hit **Delete** to confirm the deletion.

<Frame>
  ![Delete Group Dialog](https://assets.mirurobotics.com/docs/v04/images/groups/delete-dialog.png)
</Frame>

## Add a member  <AdminBadge />  <GroupManagerBadge />

To add a member to a group, navigate to the [Groups page](https://app.mirurobotics.com/groups), click the ellipses (...) on the group you want to add a member to, and select **Members** from the dropdown.

<Frame>
  ![Group Members Dropdown](https://assets.mirurobotics.com/docs/v04/images/groups/ellipses-dropdown.png)
</Frame>

A dialog will appear with a list of the members who can currently access the group.

<Frame>
  ![Group Members Dialog](https://assets.mirurobotics.com/docs/v04/images/groups/member-dialog.png)
</Frame>

To add a member, input the name of the member you want to add in the search bar at the top, and select the member.

<Frame>
  ![Group Members Search](https://assets.mirurobotics.com/docs/v04/images/groups/member-dialog-search.png)
</Frame>

## Edit a member's access  <AdminBadge />  <GroupManagerBadge />

To edit a member's access to a group, navigate to the [Groups page](https://app.mirurobotics.com/groups), click the ellipses (...) on the group you want to edit, and select **Members** from the dropdown.

<Frame>
  ![Group Members Dropdown](https://assets.mirurobotics.com/docs/v04/images/groups/ellipses-dropdown.png)
</Frame>

A dialog will appear with a list of the members who can currently access the group. Find the member you want to edit, click their role, and select the desired roles from the dropdown.

<Frame>
  ![Group Members Dialog](https://assets.mirurobotics.com/docs/v04/images/groups/member-dialog.png)
</Frame>

If the roles are not editable, that member's access is set in some ancestor group or at the workspace level. To edit the member's access at a higher level, click the **Manage access** button.

<Frame>
  ![Group Members Manage Access](https://assets.mirurobotics.com/docs/v04/images/groups/edit-member-dropdown.png)
</Frame>

A panel will appear with the member's workspace roles and all of their group roles. Use the dropdowns to edit the member's access as needed.

<Frame>
  ![Group Members Access Panel](https://assets.mirurobotics.com/docs/v04/images/groups/member-access-panel.png)
</Frame>

## Remove a member  <AdminBadge />  <GroupManagerBadge />

To remove a member from a group, navigate to the [Groups page](https://app.mirurobotics.com/groups), click the ellipses (...) on the group you want to remove a member from, and select **Members** from the dropdown.

<Frame>
  ![Group Members Dropdown](https://assets.mirurobotics.com/docs/v04/images/groups/ellipses-dropdown.png)
</Frame>

A dialog will appear with a list of the members who can currently access the group. Find the member you want to remove, click the ellipses (...) next to their name, and select **Remove access**.

<Frame>
  ![Group Members Remove Dialog](https://assets.mirurobotics.com/docs/v04/images/groups/edit-member-dropdown.png)
</Frame>
