Korzystanie z komentarzy i sugestii

Dokumenty Google umożliwiają współpracownikom współpracę poprzez pisanie komentarzy i zgłaszanie sugestii, które działają jak odroczone zmiany oczekujące na zatwierdzenie.

Za pomocą interfejsu API możesz wyświetlać sugerowane zmiany w tekście dokumentu. W wersji dla deweloperów możesz też programowo odczytywać, tworzyć, odpowiadać na wątki komentarzy i sugestii, aktualizować je oraz usuwać.

Gdy używasz metody documents.get do pobierania treści dokumentu, może ona zawierać nierozwiązane sugestie. Aby kontrolować sposób, w jaki documents.get reprezentuje sugestie, użyj opcjonalnego SuggestionsViewMode parametru. W przypadku tego parametru dostępne są te warunki filtrowania:

  • Pobieranie treści za pomocą SUGGESTIONS_INLINE, dzięki czemu tekst oczekujący na usunięcie lub wstawienie pojawia się w dokumencie.
  • Pobieranie treści jako podglądu ze wszystkimi zaakceptowanymi sugestiami.
  • Pobieranie treści jako podglądu bez sugestii, ze wszystkimi odrzuconymi sugestiami.

Jeśli nie podasz SuggestionsViewMode, interfejs API Dokumentów Google użyje ustawienia domyślnego odpowiedniego dla uprawnień bieżącego użytkownika.

Sugestie i indeksy

Jednym z powodów, dla których SuggestionsViewMode jest ważny, jest to, że indeksy w odpowiedzi mogą się różnić w zależności od tego, czy są sugestie, jak pokazano poniżej.

Treść z sugestiami Treść 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 powyższej odpowiedzi akapit zawierający wiersz „Tekst po sugestii” pokazuje różnicę podczas używania SuggestionsViewMode. Gdy 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.

Pobieranie treści bez sugestii

Ten fragment przykładowego kodu pokazuje, jak pobrać dokument jako podgląd ze wszystkimi odrzuconymi sugestiami (jeśli takie istnieją), ustawiając parametr 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 DEFAULT_FOR_CURRENT_ACCESS jako wartości parametru.

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, jak tekst jest stylizowany po sugerowanej zmianie, ale nie mówi, co się zmieniło.

  • textStyleSuggestionState, który wskazuje, jak sugestia zmienia pola textStyle.

Możesz to zobaczyć w tym fragmencie karty dokumentu, 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 fragmentów tekstu, zaczynających się w wierszach 6, 14 i 50. Sprawdź środkowy fragment tekstu:

  • Wiersz 16: jest obiekt suggestedTextStyleChanges.
  • Wiersz 18: textStyle określa różne formatowanie.
  • Wiersz 36: textStyleSuggestionState informuje, że tylko pogrubiona część tej specyfikacji była sugestią.
  • Wiersz 42: kursywa tego fragmentu tekstu jest częścią bieżącego dokumentu (i nie jest objęta sugestią).

Tylko funkcje stylu ustawione na true w textStyleSuggestionState są częścią sugestii.

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 wykonywania aktualizacji zbiorczych obejmujących komentarze lub sugestie należy monitorować potencjalne częściowe awarie. Więcej informacji znajdziesz w sekcji Stan aktualizacji komentarzy i sugestii.

Wstawianie komentarza

Aby wstawić wątek komentarza, użyj InsertCommentRequest obiektu. Musisz podać treść komentarza i lokalizację kotwicy (np. zakres), do której jest dołączony komentarz.

Ten przykład w formacie JSON dodaje nieprzypisany wątek komentarza do określonego zakresu:

{
  "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 komentarz lub wątek sugestii albo rozwiązać lub ponownie otworzyć wątek, użyj AddCommentReplyRequest.

Odpowiedź jest reprezentowana przez Post obiekt. Obiekt Post zawiera content odpowiedzi i opcjonalnie może określać commentAction (aby RESOLVE lub REOPEN wątek).

Ten przykład odpowiada na istniejący wątek komentarza:

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

Ten przykład rozwiązuje wątek komentarza, który nie wymaga treści:

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

Edytowanie posta

Aby edytować tekst posta, którego jesteś autorem, użyj UpdateCommentPostRequest. Musisz określić identyfikator wątku (albo commentId albo suggestionId), postId posta, który chcesz edytować, oraz nową treść w postaci zwykłego tekstu content.

Pamiętaj, że nie możesz edytować głównego posta 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 komentarza: aby usunąć cały wątek komentarza, użyj DeleteCommentRequest. Wątek komentarza możesz usunąć tylko wtedy, gdy jesteś autorem głównego posta w tym wątku.
  • Usuwanie odpowiedzi: aby usunąć konkretny post z odpowiedzią, użyj DeleteCommentReplyRequest. Możesz usuwać tylko odpowiedzi, których jesteś autorem. Nie możesz usuwać postów z odpowiedziami, które zawierają działania lub osoby przypisane.

Ten przykład usuwa wątek komentarza:

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

Pisanie sugestii i zarządzanie wątkami sugestii

Możesz pisać zmiany jako sugestie, a nie bezpośrednie zmiany, oraz programowo akceptować, odrzucać lub usuwać wątki sugestii.

Podczas wykonywania aktualizacji zbiorczych obejmujących sugestie należy monitorować potencjalne częściowe awarie. Więcej informacji znajdziesz w sekcji 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

Gdy używasz WriteMode.SUGGEST, te typy żądań nie są obsługiwane i zwrócą błąd:

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

Nie możesz też sugerować zmian formatu dokumentu ani ustawień nagłówków i stopek. W przypadku 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ę: aby zaakceptować sugestię, użyj AcceptSuggestionRequest. Wymaga to uprawnień do edycji dokumentu.
  • Odrzuć sugestię: aby odrzucić sugestię, użyj RejectSuggestionRequest. Wymaga to uprawnień do edycji dokumentu lub bycia autorem sugestii.
  • Usuń sugestię: aby usunąć sugestię, użyj DeleteSuggestionRequest. Wymaga to bycia autorem sugestii.

Ten przykład akceptuje wątek sugestii:

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

Stan aktualizacji komentarzy i sugestii

Żądania, które wymagają zapisania wątków komentarzy lub sugestii (np. wstawianie komentarzy, dodawanie odpowiedzi lub zgłaszanie sugestii), mogą powodować częściowe awarie. W takich przypadkach zmiany w modelu dokumentu (np. wstawianie lub usuwanie tekstu) mogą zostać pomyślnie zatwierdzone w modelu Dokumentów, ale powiązane komentarze lub sugestie mogą nie zostać zapisane.

Aby sprawdzić, czy aktualizacje komentarzy lub sugestii zostały pomyślnie zastosowane, sprawdź pole commentUpdateState w BatchUpdateDocumentResponse.

W CommentUpdateState zwracane są te stany:

  • NO_UPDATES_REQUESTED: w operacji zbiorczej nie zażądano żadnych aktualizacji komentarzy ani sugestii.
  • ALL_SAVED: wszystkie żądane aktualizacje komentarzy lub sugestii zostały pomyślnie 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.