Utiliser des commentaires et des suggestions

Google Docs permet aux collaborateurs de travailler ensemble en rédigeant des commentaires et en faisant des suggestions qui agissent comme des modifications différées en attente d'approbation.

Vous pouvez utiliser l'API pour afficher les modifications suggérées directement dans le texte du document. Dans la preview développeur, vous pouvez également lire, créer, modifier, supprimer des fils de commentaires et de suggestions, ou y répondre, de façon programmatique.

Lorsque vous utilisez la documents.get méthode pour récupérer le contenu d'un document, celui-ci peut inclure des suggestions non résolues. Pour contrôler la façon dont documents.get représente les suggestions, utilisez le paramètre facultatif SuggestionsViewMode. Les conditions de filtrage suivantes sont disponibles avec ce paramètre :

  • Obtenez du contenu avec SUGGESTIONS_INLINE, afin que le texte en attente de suppression ou d'insertion apparaisse dans le document.
  • Obtenez un aperçu du contenu avec toutes les suggestions acceptées.
  • Obtenez un aperçu du contenu sans suggestions, avec toutes les suggestions refusées.

Si vous ne fournissez pas SuggestionsViewMode, l'API Google Docs utilise un paramètre par défaut adapté aux droits d'accès de l'utilisateur actuel.

Pour contrôler si les commentaires sont inclus lors de la récupération d'un document, utilisez le paramètre commentsViewMode facultatif. Si vous définissez commentsViewMode sur COMMENTS_VIEW_MODE_INCLUDED, vous devez également définir includeTabsContent sur true. De plus, si vous utilisez un masque de champ qui fait référence au champ tabs (ou à un sous-champ), l'API traite implicitement la requête comme si vous aviez défini includeTabsContent sur true.

Suggestions et index

L'une des raisons pour lesquelles SuggestionsViewMode est important est que les index de la réponse peuvent varier selon qu'il existe ou non des suggestions, comme illustré dans l'exemple suivant.

Contenu avec suggestions Contenu sans suggestions
{
 "tabs": [
  {
   "documentTab": {
    "body": {
     "content": [
      {
       "startIndex": 1,
       "endIndex": 31,
       "paragraph": {
        "elements": [
         {
          "startIndex": 1,
          "endIndex": 31,
          "textRun": {
           "content": "Text preceding the suggestion\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      },
      {
       "startIndex": 31,
       "endIndex": 51,
       "paragraph": {
        "elements": [
         {
          "startIndex": 31,
          "endIndex": 50,
          "textRun": {
           "content": "Suggested insertion",
           "suggestedInsertionIds": [
            "suggest.vcti8ewm4mww"
           ],
           "textStyle": {}
          }
         },
         {
          "startIndex": 50,
          "endIndex": 51,
          "textRun": {
           "content": "\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      },
      {
       "startIndex": 51,
       "endIndex": 81,
       "paragraph": {
        "elements": [
         {
          "startIndex": 51,
          "endIndex": 81,
          "textRun": {
           "content": "Text following the suggestion\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      }
     ]
    }
   }
  }
 ]
},

{
 "tabs": [
  {
   "documentTab": {
    "body": {
     "content": [
      {
       "startIndex": 1,
       "endIndex": 31,
       "paragraph": {
        "elements": [
         {
          "startIndex": 1,
          "endIndex": 31,
          "textRun": {
           "content": "Text preceding the suggestion\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      },
      {
       "startIndex": 31,
       "endIndex": 32,
       "paragraph": {
        "elements": [
         {
          "startIndex": 31,
          "endIndex": 32,
          "textRun": {
           "content": "\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      },
      {
       "startIndex": 32,
       "endIndex": 62,
       "paragraph": {
        "elements": [
         {
          "startIndex": 32,
          "endIndex": 62,
          "textRun": {
           "content": "Text following the suggestion\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      }
     ]
    }
   }
  }
 ]
},

Dans la réponse précédente, le paragraphe contenant la ligne "Text following the suggestion" (Texte suivant la suggestion) montre la différence lors de l'utilisation de SuggestionsViewMode. Lorsque la valeur est définie sur SUGGESTIONS_INLINE, le startIndex du ParagraphElement commence à 51 et le endIndex s'arrête à 81. Sans suggestions, la plage startIndex et endIndex va de 32 à 62.

Obtenir du contenu sans suggestions

L'exemple de code partiel suivant montre comment obtenir un aperçu d'un document avec toutes les suggestions refusées (le cas échéant) en définissant le paramètre SuggestionsViewMode sur PREVIEW_WITHOUT_SUGGESTIONS.

Java

final string SUGGEST_MODE = "PREVIEW_WITHOUT_SUGGESTIONS";
Document doc =
    service
        .documents()
        .get(DOCUMENT_ID)
        .setIncludeTabsContent(true)
        .setSuggestionsViewMode(SUGGEST_MODE)
        .execute();

Python

SUGGEST_MODE = "PREVIEW_WITHOUT_SUGGESTIONS"
result = (
  service.documents()
  .get(
      documentId=DOCUMENT_ID,
      includeTabsContent=True,
      suggestionsViewMode=SUGGEST_MODE,
  )
  .execute()
)

Omettre le paramètre SuggestionsViewMode revient à fournir DEFAULT_FOR_CURRENT_ACCESS comme valeur de paramètre.

Suggestions de style

Les documents peuvent également contenir des suggestions de style. Il s'agit de modifications suggérées concernant la mise en forme et la présentation, plutôt que le contenu.

Contrairement aux insertions ou suppressions de texte, elles ne décalent pas les index (bien qu'elles puissent diviser un TextRun en plus petits morceaux), mais ajoutent simplement des annotations concernant la modification de style suggérée.

L'une de ces annotations est un SuggestedTextStyle, qui comporte deux parties :

  • Le textStyle, qui décrit la mise en forme du texte après la modification suggérée, mais n'indique pas ce qui a changé.

  • Le textStyleSuggestionState, qui indique comment la suggestion modifie les champs du textStyle.

Vous pouvez le constater dans l'extrait d'onglet du document suivant, qui inclut une modification de style suggérée :

[01] "paragraph": {
[02]    "elements": [
[03]        {
[04]            "endIndex": 106,
[05]            "startIndex": 82,
[06]            "textRun": {
[07]                "content": "Some text that does not ",
[08]                "textStyle": {}
[09]            }
[10]        },
[11]        {
[12]            "endIndex": 115,
[13]            "startIndex": 106,
[14]            "textRun": {
[15]                "content": "initially",
[16]                "suggestedTextStyleChanges": {
[17]                    "suggest.xymysbs9zldp": {
[18]                        "textStyle": {
[19]                            "backgroundColor": {},
[20]                            "baselineOffset": "NONE",
[21]                            "bold": true,
[22]                            "fontSize": {
[23]                                "magnitude": 11,
[24]                                "unit": "PT"
[25]                            },
[26]                            "foregroundColor": {
[27]                                "color": {
[28]                                    "rgbColor": {}
[29]                                }
[30]                            },
[31]                            "italic": false,
[32]                            "smallCaps": false,
[33]                            "strikethrough": false,
[34]                            "underline": false
[35]                        },
[36]                        "textStyleSuggestionState": {
[37]                            "boldSuggested": true,
[38]                            "weightedFontFamilySuggested": true
[39]                        }
[40]                    }
[41]                },
[42]                "textStyle": {
[43]                    "italic": true
[44]                }
[45]            }
[46]        },
[47]        {
[48]            "endIndex": 143,
[49]            "startIndex": 115,
[50]            "textRun": {
[51]                "content": " contain any boldface text.\n",
[52]                "textStyle": {}
[53]            }
[54]        }
[55]    ],
[56]    "paragraphStyle": {
[57]        "direction": "LEFT_TO_RIGHT",
[58]        "namedStyleType": "NORMAL_TEXT"
[59]    }
[60] }

Dans l'exemple précédent, le paragraphe se compose de trois passages de texte, commençant aux lignes 6, 14 et 50. Examinez le passage de texte du milieu :

  • Ligne 16 : il existe un objet suggestedTextStyleChanges.
  • Ligne 18 : le textStyle spécifie différentes mises en forme.
  • Ligne 36 : le textStyleSuggestionState indique que seule la partie en gras de cette spécification était la suggestion.
  • Ligne 42 : la mise en forme en italique de ce passage de texte fait partie du document actuel (et n'est pas affectée par la suggestion).

Seules les fonctionnalités de style définies sur true dans le textStyleSuggestionState font partie de la suggestion.

Créer et gérer des commentaires

Vous pouvez ajouter des commentaires et des réponses, modifier des commentaires, et supprimer des commentaires ou des réponses de façon programmatique à l'aide de la méthode documents.batchUpdate.

Lorsque vous effectuez des mises à jour par lot impliquant des commentaires ou des suggestions, vous devez surveiller les éventuels échecs partiels. Pour en savoir plus, consultez l'état de mise à jour des commentaires et des suggestions.

Insérer un commentaire

Pour insérer un fil de commentaires, utilisez l'InsertCommentRequest objet. Vous devez fournir le contenu du texte du commentaire et un emplacement d'ancrage (tel qu'une plage) auquel le commentaire est associé.

L'exemple JSON suivant ajoute un fil de commentaires non attribué à la plage spécifiée :

{
  "requests": [
    {
      "insertComment": {
        "content": "This is a comment added via the API.",
        "range": {
          "startIndex": 10,
          "endIndex": 25
        }
      }
    }
  ]
}

Vous pouvez attribuer un commentaire à un utilisateur spécifique en fournissant son adresse e-mail dans le champ assigneeEmailAddress :

{
  "requests": [
    {
      "insertComment": {
        "content": "Please review this paragraph.",
        "assigneeEmailAddress": "user@example.com",
        "range": {
          "startIndex": 10,
          "endIndex": 25
        }
      }
    }
  ]
}

Ajouter une réponse ou effectuer une action

Pour répondre à un fil de commentaires ou de suggestions, ou pour résoudre ou rouvrir un fil, utilisez AddCommentReplyRequest.

Une réponse est représentée par un Post objet. L'objet Post contient le content de la réponse et peut éventuellement spécifier une commentAction (pour RESOLVE ou REOPEN le fil).

Vous pouvez également réattribuer un fil de commentaires en spécifiant un nouveau assigneeEmail dans l'objet Post.

L'exemple suivant répond à un fil de commentaires existant :

{
  "requests": [
    {
      "addCommentReply": {
        "commentId": "comment_thread_id",
        "post": {
          "content": "Replying to the comment thread."
        }
      }
    }
  ]
}

L'exemple suivant résout un fil de commentaires, qui ne nécessite pas de contenu :

{
  "requests": [
    {
      "addCommentReply": {
        "commentId": "comment_thread_id",
        "post": {
          "commentAction": "RESOLVE"
        }
      }
    }
  ]
}

L'exemple JSON suivant montre comment réattribuer un fil de commentaires :

{
  "requests": [
    {
      "addCommentReply": {
        "commentId": "comment_thread_id",
        "post": {
          "content": "Replying to the comment thread.",
          "assigneeEmail": "user@example.com"
        }
      }
    }
  ]
}

Modifier un article

Pour modifier le contenu textuel d'un article que vous avez créé, utilisez UpdateCommentPostRequest. Vous devez spécifier l'ID du fil (commentId ou suggestionId), le postId de l'article que vous souhaitez modifier et le nouveau content en texte brut.

Notez que vous ne pouvez pas modifier l'article principal d'un fil de suggestions (car il est généré par des modifications en mode suggestion).

{
  "requests": [
    {
      "updateCommentPost": {
        "commentId": "comment_thread_id",
        "postId": "post_id",
        "content": "This is the updated comment text."
      }
    }
  ]
}

Supprimer des commentaires et des réponses

  • Supprimer un fil de commentaires : pour supprimer un fil de commentaires entier, utilisez DeleteCommentRequest. Vous ne pouvez supprimer un fil de commentaires que si vous êtes l'auteur de l'article principal du fil.
  • Supprimer une réponse : pour supprimer un article de réponse spécifique, utilisez DeleteCommentReplyRequest. Vous ne pouvez supprimer que les réponses que vous avez créées. Vous ne pouvez pas supprimer les articles de réponse qui contiennent des actions ou des destinataires.

L'exemple suivant supprime un fil de commentaires :

{
  "requests": [
    {
      "deleteComment": {
        "commentId": "comment_thread_id"
      }
    }
  ]
}

Rédiger des suggestions et gérer des fils de suggestions

Vous pouvez rédiger des modifications sous forme de suggestions plutôt que de modifications directes, et accepter, refuser ou supprimer des fils de suggestions de façon programmatique.

Lorsque vous effectuez des mises à jour par lot impliquant des suggestions, vous devez surveiller les éventuels échecs partiels. Pour en savoir plus, consultez l'état de mise à jour des commentaires et des suggestions.

Créer des suggestions à l'aide du mode suggestion

Pour appliquer des modifications sous forme de suggestions, définissez le champ writeMode de l'objet WriteControl sur SUGGEST dans votre requête de mise à jour groupée. Toutes les mises à jour de la requête sont traitées comme des suggestions.

{
  "requests": [
    {
      "insertText": {
        "text": "suggested insertion text",
        "location": {
          "index": 1
        }
      }
    }
  ],
  "writeControl": {
    "writeMode": "SUGGEST"
  }
}

Requêtes non acceptées en mode suggestion

Lorsque vous utilisez WriteMode.SUGGEST, les types de requêtes suivants ne sont pas acceptés et renvoient une erreur :

  • AddDocumentTab
  • CreateNamedRange
  • DeleteFooter
  • DeleteHeader
  • DeleteNamedRange
  • DeleteTab
  • UpdateDocumentTabProperties
  • UpdateTableColumnProperties

De plus, vous ne pouvez pas suggérer de modifications concernant le format du document ni les paramètres d'en-tête et de pied de page. Dans UpdateDocumentStyle, les suggestions ne sont pas acceptées pour les types de styles suivants :

  • documentFormat
  • useEvenPageHeaderFooter
  • useFirstPageHeaderFooter

Accepter, refuser ou supprimer des fils de suggestions

Vous pouvez gérer les fils de suggestions à l'aide des requêtes suivantes :

  • Accepter une suggestion : utilisez AcceptSuggestionRequest pour accepter la suggestion. Vous devez disposer des droits de modification sur le document.
  • Refuser une suggestion : utilisez RejectSuggestionRequest pour refuser la suggestion. Vous devez disposer des droits de modification sur le document ou être l'auteur de la suggestion.
  • Supprimer une suggestion : utilisez DeleteSuggestionRequest pour supprimer la suggestion. Vous devez être l'auteur de la suggestion.

L'exemple suivant accepte un fil de suggestions :

{
  "requests": [
    {
      "acceptSuggestion": {
        "suggestionId": "suggestion_thread_id"
      }
    }
  ]
}

État de mise à jour des commentaires et des suggestions

Les requêtes qui nécessitent l'enregistrement de fils de commentaires ou de suggestions (par exemple, l'insertion de commentaires, l'ajout de réponses ou la formulation de suggestions) peuvent entraîner des échecs partiels. Dans ce cas, les modifications du modèle de document (telles que les insertions ou suppressions de texte) peuvent être correctement validées dans le modèle Docs, mais les commentaires ou suggestions associés peuvent ne pas être enregistrés.

Vous pouvez vérifier si les mises à jour des commentaires ou des suggestions ont été appliquées en consultant le commentUpdateState dans le BatchUpdateDocumentResponse.

Les états suivants sont renvoyés dans CommentUpdateState :

  • NO_UPDATES_REQUESTED : aucune mise à jour de commentaire ou de suggestion n'a été demandée dans l'opération par lot.
  • ALL_SAVED : toutes les mises à jour de commentaires ou de suggestions demandées ont été appliquées.
  • ALL_FAILED_UNKNOWN_REASON : toutes les mises à jour de commentaires ou de suggestions demandées n'ont pas pu être enregistrées, même si les modifications du modèle Docs ont peut-être été validées.