Dokumenty Google umożliwiają współpracownikom pisanie komentarzy i dodawanie sugestii, które działają jak odroczone zmiany czekające na zatwierdzenie.
Za pomocą interfejsu API możesz wyświetlać sugerowane zmiany w tekście dokumentu. Możesz też programowo odczytywać, tworzyć, aktualizować i usuwać wątki komentarzy i sugestii oraz na nie odpowiadać.
Gdy używasz metody
documents.get do pobierania treści dokumentu, mogą one zawierać nierozwiązane sugestie. Aby określić, w jaki sposób documents.get ma przedstawiać sugestie, użyj opcjonalnego parametru SuggestionsViewMode. W przypadku tego parametru dostępne są te warunki filtrowania:
- Pobierz treść za pomocą
SUGGESTIONS_INLINE, aby w dokumencie pojawił się tekst oczekujący na usunięcie lub wstawienie. - Wyświetl podgląd treści ze wszystkimi zaakceptowanymi sugestiami.
- Otrzymuj treści w formie podglądu bez sugestii, przy czym wszystkie sugestie są odrzucane.
Jeśli nie podasz wartości SuggestionsViewMode, interfejs Google Docs API użyje ustawienia domyślnego odpowiedniego dla uprawnień bieżącego użytkownika.
Aby określić, czy komentarze mają być uwzględniane podczas pobierania dokumentu, użyj opcjonalnego parametru commentsViewMode.
Komentarze są zwracane tylko wtedy, gdy sugestie są zwracane w tekście. Podczas ustawiania
commentsViewMode musisz też skonfigurować
suggestionsViewMode
w ten sposób:
- Jeśli wartość parametru
commentsViewModetoCOMMENTS_VIEW_MODE_INCLUDED, parametrsuggestionsViewModemusi mieć wartośćSUGGESTIONS_INLINE. - Jeśli wartość
commentsViewModetoCOMMENTS_VIEW_MODE_DEFAULT_FOR_CURRENT_ACCESS, wartośćsuggestionsViewModemusi być ustawiona naSUGGESTIONS_INLINElubDEFAULT_FOR_CURRENT_ACCESS.
Jeśli ustawisz commentsViewMode na COMMENTS_VIEW_MODE_INCLUDED, musisz też ustawić includeTabsContent na true. Jeśli używasz maski pola, która odwołuje się do pola tabs (lub dowolnego pola podrzędnego), interfejs API traktuje żądanie tak, jakby pole includeTabsContent miało wartość true.
Sugestie i indeksy
Symbol SuggestionsViewMode jest ważny, ponieważ indeksy w odpowiedzi mogą się różnić w zależności od tego, czy są sugestie, jak pokazano w poniższym przykładzie.
| Treści z sugestiami | Treści bez sugestii |
|---|---|
{
"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"
}
}
}
]
}
}
}
]
},
|
W poprzedniej odpowiedzi akapit zawierający wiersz „Text following the
suggestion” pokazuje różnicę w przypadku użycia znaku SuggestionsViewMode. Jeśli wartość jest ustawiona na SUGGESTIONS_INLINE, startIndex elementu ParagraphElement zaczyna się od 51, a endIndex kończy się na 81. Bez sugestii zakres startIndex i endIndex wynosi od 32 do 62.
Otrzymywanie treści bez sugestii
Poniższy przykładowy kod pokazuje, jak uzyskać dokument w formie podglądu ze wszystkimi odrzuconymi sugestiami (jeśli takie istnieją) przez ustawienie parametru SuggestionsViewMode na 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() )
Pominięcie parametru SuggestionsViewMode jest równoznaczne z podaniem wartości parametru DEFAULT_FOR_CURRENT_ACCESS.
Sugestie dotyczące stylu
Dokumenty mogą też zawierać sugestie dotyczące stylu. Są to sugerowane zmiany formatowania i prezentacji, a nie zmiany treści.
W przeciwieństwie do wstawiania lub usuwania tekstu nie powodują one przesunięcia indeksów (chociaż mogą podzielić TextRun na mniejsze części), ale dodają adnotacje dotyczące sugerowanej zmiany stylu.
Jedną z takich adnotacji jest SuggestedTextStyle, która składa się z 2 części:
textStyle, który opisuje styl tekstu po wprowadzeniu sugerowanej zmiany, ale nie informuje, co się zmieniło.textStyleSuggestionState, który wskazuje, jak sugestia zmienia polatextStyle.
Możesz to zobaczyć na wyciągu z karty dokumentu poniżej, który zawiera sugerowaną zmianę stylu:
[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] }
W powyższym przykładzie akapit składa się z 3 ciągów tekstu, które zaczynają się w wierszach 6, 14 i 50. Sprawdź środkowy fragment tekstu:
- Wiersz 16: jest obiekt
suggestedTextStyleChanges. - Wiersz 18: znak
textStyleokreśla różne formatowanie. - Wiersz 36: znak
textStyleSuggestionStateinformuje, że sugestia dotyczy tylko pogrubionej części tej specyfikacji. - Wiersz 42: kursywa w tym fragmencie tekstu jest częścią bieżącego dokumentu (i nie ma na nią wpływu sugestia).
Sugerowane są tylko funkcje stylu ustawione na true w textStyleSuggestionState.
Tworzenie komentarzy i zarządzanie nimi
Za pomocą metody documents.batchUpdate możesz programowo dodawać komentarze i odpowiedzi, edytować komentarze oraz usuwać komentarze lub odpowiedzi.
Podczas przeprowadzania aktualizacji zbiorczych obejmujących komentarze lub sugestie należy monitorować potencjalne częściowe niepowodzenia. Więcej informacji znajdziesz w artykule Stan aktualizacji komentarzy i sugestii.
Wstawianie komentarza
Aby wstawić wątek komentarzy, użyj obiektu InsertCommentRequest. Musisz podać treść komentarza i miejsce zakotwiczenia (np. zakres), do którego jest on dołączony.
Poniższy przykład JSON dodaje do określonego zakresu wątek komentarzy bez przypisanego użytkownika:
{
"requests": [
{
"insertComment": {
"content": "This is a comment added via the API.",
"range": {
"startIndex": 10,
"endIndex": 25
}
}
}
]
}
Możesz przypisać komentarz do konkretnego użytkownika, podając jego adres e-mail w polu assigneeEmailAddress:
{
"requests": [
{
"insertComment": {
"content": "Please review this paragraph.",
"assigneeEmailAddress": "user@example.com",
"range": {
"startIndex": 10,
"endIndex": 25
}
}
}
]
}
Dodawanie odpowiedzi lub podejmowanie działań
Aby odpowiedzieć na wątek komentarza lub sugestii albo zamknąć lub ponownie otworzyć wątek, użyj ikony AddCommentReplyRequest.
Odpowiedź jest reprezentowana przez obiekt Post.
Obiekt Post zawiera odpowiedź content i może opcjonalnie określać commentAction (aby RESOLVE lub REOPEN wątek).
Możesz też ponownie przypisać wątek komentarzy, podając nowy assigneeEmail w obiekcie Post.
Poniżej znajdziesz przykładowe odpowiedzi na istniejący wątek komentarzy:
{
"requests": [
{
"addCommentReply": {
"commentId": "comment_thread_id",
"post": {
"content": "Replying to the comment thread."
}
}
}
]
}
Poniższy przykład rozwiązuje wątek komentarza, który nie wymaga treści:
{
"requests": [
{
"addCommentReply": {
"commentId": "comment_thread_id",
"post": {
"commentAction": "RESOLVE"
}
}
}
]
}
Poniższy przykład JSON pokazuje, jak ponownie przypisać wątek komentarzy:
{
"requests": [
{
"addCommentReply": {
"commentId": "comment_thread_id",
"post": {
"content": "Replying to the comment thread.",
"assigneeEmail": "user@example.com"
}
}
}
]
}
Edytowanie posta
Aby edytować tekst posta, którego jesteś autorem, użyj ikony UpdateCommentPostRequest.
Musisz podać identyfikator wątku (commentId lub suggestionId), postId posta, który chcesz edytować, oraz nowy tekst content.
Pamiętaj, że nie możesz edytować głównego posta w wątku sugestii (ponieważ są one generowane przez zmiany w trybie sugestii).
{
"requests": [
{
"updateCommentPost": {
"commentId": "comment_thread_id",
"postId": "post_id",
"content": "This is the updated comment text."
}
}
]
}
Usuwanie komentarzy i odpowiedzi
- Usuwanie wątku komentarzy: aby usunąć cały wątek komentarzy, kliknij
DeleteCommentRequest. Wątek komentarzy możesz usunąć tylko wtedy, gdy jesteś autorem pierwszego posta w tym wątku. - Usuwanie odpowiedzi: aby usunąć konkretną odpowiedź, użyj
DeleteCommentReplyRequest. Możesz usuwać tylko odpowiedzi, które zostały przez Ciebie napisane. Nie możesz usuwać postów z odpowiedziami, które zawierają działania lub osoby przypisane.
Ten przykładowy kod usuwa wątek komentarzy:
{
"requests": [
{
"deleteComment": {
"commentId": "comment_thread_id"
}
}
]
}
Pisanie sugestii i zarządzanie wątkami sugestii
Możesz wprowadzać zmiany w formie sugestii, a nie bezpośrednich edycji, oraz programowo akceptować, odrzucać i usuwać wątki sugestii.
Podczas przeprowadzania aktualizacji zbiorczych obejmujących sugestie należy monitorować potencjalne częściowe niepowodzenia. Więcej informacji znajdziesz w artykule Stan aktualizacji komentarzy i sugestii.
Tworzenie sugestii w trybie sugestii
Aby zastosować zmiany jako sugestie, ustaw pole writeMode obiektu WriteControl na SUGGEST w żądaniu aktualizacji zbiorczej. Wszystkie aktualizacje w żądaniu są przetwarzane jako sugestie.
{
"requests": [
{
"insertText": {
"text": "suggested insertion text",
"location": {
"index": 1
}
}
}
],
"writeControl": {
"writeMode": "SUGGEST"
}
}
Nieobsługiwane żądania w trybie sugestii
W przypadku korzystania z WriteMode.SUGGEST te typy żądań nie są obsługiwane i zwracają błąd:
AddDocumentTabCreateNamedRangeDeleteFooterDeleteHeaderDeleteNamedRangeDeleteTabUpdateDocumentTabPropertiesUpdateTableColumnProperties
Nie możesz też sugerować zmian w formacie dokumentu ani w ustawieniach nagłówka i stopki. W UpdateDocumentStyle sugestie nie są obsługiwane w przypadku tych typów stylów:
documentFormatuseEvenPageHeaderFooteruseFirstPageHeaderFooter
Akceptowanie, odrzucanie i usuwanie wątków sugestii
Wątkami sugestii możesz zarządzać za pomocą tych żądań:
- Zaakceptuj sugestię: użyj
AcceptSuggestionRequest, aby zaakceptować sugestię. Wymaga to uprawnień do edycji dokumentu. - Odrzucić sugestię: aby odrzucić sugestię, użyj
RejectSuggestionRequest. Wymaga to uprawnień do edycji dokumentu lub bycia autorem sugestii. - Usuń sugestię: kliknij
DeleteSuggestionRequest, aby usunąć sugestię. Musisz być autorem sugestii.
Poniższy przykład akceptuje wątek sugestii:
{
"requests": [
{
"acceptSuggestion": {
"suggestionId": "suggestion_thread_id"
}
}
]
}
Stan aktualizacji komentarza i sugestii
Żądania, które wymagają zapisania wątków komentarzy lub sugestii (np. wstawianie komentarzy, dodawanie odpowiedzi lub zgłaszanie sugestii), mogą być częściowo nieudane. W takich przypadkach zmiany w modelu dokumentu (np. wstawienia lub usunięcia tekstu) mogą zostać pomyślnie wprowadzone w modelu Dokumentów, ale powiązane z nimi komentarze lub sugestie mogą nie zostać zapisane.
Aby sprawdzić, czy aktualizacje komentarzy lub sugestii zostały zastosowane, sprawdź pole commentUpdateState w BatchUpdateDocumentResponse.
W odpowiedzi CommentUpdateState zwracane są te stany:
NO_UPDATES_REQUESTED: w operacji wsadowej nie zażądano aktualizacji komentarzy ani sugestii.ALL_SAVED: wszystkie zmiany w komentarzach lub sugestiach zostały zastosowane.ALL_FAILED_UNKNOWN_REASON: nie udało się zapisać wszystkich żądanych aktualizacji komentarzy lub sugestii, mimo że zmiany w modelu Dokumentów mogły zostać zatwierdzone.