Korzystanie z komentarzy i sugestii

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 commentsViewMode to COMMENTS_VIEW_MODE_INCLUDED, parametr suggestionsViewMode musi mieć wartość SUGGESTIONS_INLINE.
  • Jeśli wartość commentsViewMode to COMMENTS_VIEW_MODE_DEFAULT_FOR_CURRENT_ACCESS, wartość suggestionsViewMode musi być ustawiona na SUGGESTIONS_INLINE lub DEFAULT_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 pola textStyle.

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 textStyle określa różne formatowanie.
  • Wiersz 36: znak textStyleSuggestionState informuje, ż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:

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

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:

  • documentFormat
  • useEvenPageHeaderFooter
  • useFirstPageHeaderFooter

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.