Historia zmian postu

0

Hej, robie strone w stylu wikipedii, czyli mam jakis artykul i chcialbym moc pozwolic uzytkownikom go edytowac. Ja jako moderator powinienem wybierac jakie zmiany dopuszczam a jakie nie oraz przechowywac historie wszystkich zmian (odrzuconych i zaakceptowanych). Wstepnie wyobrazam to sobie tak:

  • ktos wchodzi na strone -> klika edytuj -> otwiera mu sie edytor z obecna zawartoscia strony
  • wprowadza swoje zmiany, klika "przeslij do akceptacji" i ja jako administrator widze w bazie dla danego artykulu zmiane w polu "pendingChanges" (np. array przechowujacy {author: User, content: string} czyli wszystkie oczekujace zmiany oraz ich autorow.
  • moge sobie porownac (np. uzywajac https://www.npmjs.com/package/react-diff-viewer) obie wersje (cos w stylu gita) i albo zaakceptowac albo odrzucic zmiane

Problem pojawia sie jesli np. rozni uzytkownicy zaproponuja rozne zmiany do tego samego artykulu i wtedy w pendingChanges mam dwie zmiany i nawet jak jedna zaakceptuje porownujac do obecnego artykulu (pierwsza ktora wplynela) to bedzie mi ciezko porownac ta druge zmiane bo ona jest oparta o artykul jeszcze sprzed pierwszej zmiany.

Jak to poprawnie rozwiazac? Jak mniej wiecej ustrukturyzowac baze danych zeby wygodnie przechowywac oczekujace i zaakceptowane zmiany i je porownywac? Bede wdzieczny za wszelkie sugestie dotyczace metodologii i potencjalnych bibliotek

1

@Kokos123 Robiłem kilka lat temu coś takiego. Wykorzystałem git, ma wszystko co potrzeba, łatwo było sobie postawić hostowanie (bitbucket) i oszczędził mi sporo roboty. Korzystałem z niego jak z bazy danych.

2

Problem znany najszerzej z gita - merge conflict. Dwie strony edytują jeden plik w tym samym momencie. Natomiast trzeba zwrócić uwagę na to, że dwie zmiany na raz mogą być niekonfliktowe, np: oryginalny tekst:

Przygody Ani i jej kotka

Ania miała 8 lat, gdy przygarnęła zwierzaka do domu i potem żyli długo i szczęśliwie.

Potem użytkownik A zmienia:

Przygody Ani i jej pieska

Ania miała 8 lat, gdy przygarnęła zwierzaka do domu i potem żyli długo i szczęśliwie.

A użytkownik B zmienia (pierwotną wersję) na:

Przygody Ani i jej kotka

Ania miała 9 lat, gdy przygarnęła zwierzaka do domu i potem żyli długo i szczęśliwie.

Można to bezkonfliktowo połączyć w jeden dokument, możesz sobie w panelu zaakceptować najpierw jedną zmianę, a potem drugą, w dowolnej kolejności.

Gorzej jest, gdyby zmienili ten sam fragment tekstu, np. A zmienił by wiek na 9, a B na 7.

Tak czy siak - do czegoś takiego potrzebujesz narzędzia, które rozumie format tekstu, w którym go przechowujesz - czy to zwykły tekst, czy HTML, czy Markdown czy jeszcze coś innego - i jest w stanie wygenerować listę zmian, a w przypadku wielu źródeł tych zmian - listę miejsc konfliktowych.

Tak mogłoby wyglądać okno rozwiązywania konfliktów (tak, to jest rzecz do której najlepiej mieć super szeroki monitor :)):

screenshot-20240305165741.png
Nie znam niestety żadnego narzędzia, które pchnie cię dalej. Tutaj jest projekt jakiś, który w przeglądarce pozwala rozwiązywać konflikty w gicie: https://github.com/joelgriffith/sickmerge - możliwe, że znajdziesz tam jakąś inspirację - ale raczej będzie to niekompatybilne z react-diff-viewer - ogółem wydaje mi się, że react-diff-viewer będziesz musiał porzucić i stworzyć coś własnego.

Kupa roboty przed Tobą. Powodzenia!

A i w sumie na koniec - cokolwiek robisz - przemyśl na ile taka funkcja jest Ci na serio potrzebna - czy jest to przypadek, który występuje raz na godzinę czy raczej raz na 3 miesiące. Może po prostu blokować edycję, gdy już jest jakaś oczekująca to nie będzie najgorszy pomysł - przynajmniej na razie?

1
Kokos123 napisał(a):

Jak to poprawnie rozwiazac? Jak mniej wiecej ustrukturyzowac baze danych zeby wygodnie przechowywac oczekujace i zaakceptowane zmiany i je porownywac?

Niech Cię ręka boska broni żeby to robić bazą. W bazie po prostu trzymaj dwie wersje jako cały tekst, a porównywanie i mergowanie tych zmian zrób normalnie w logice.

A tak szczerze mówiąc - to masz większy kłopot. Próbujesz rozwiązać problem który nie istnieje, a na to jest jedna odpowiedź: YAGNI. Napisz sobie tą wiki z normalną edycją postów, i zacznij rozwiązywać problem mergowania konfliktów jak faktycznie taki use case się pojawi.

0

@Riddle oczywiście w bazie będę przechowywał cały string (HTML pochodzący z RichText edytora).

@dzek69 Dzieki za obszerna odpowiedz. Ogolnie myślałem żeby zrobić to tak że po prostu mam stary HTML i nowy (po zmianach uzytkownika), wrzuca to sobie do HTML react differa czy innego toola ktory porownuje dwa stringi i podswietla roznice i akceptuje. Po akcepcie zastepuje caly stary HTML tym nowym i stary wrzucam do historii zmian dzieki czemu dowolny uzytkownik bedzie mogl sobie sprawdzic kto co zmienil w przeszlosci (tj widziec wklad kazdego uzytkownika). Robiac w ten sposob nie dzialalyby nawet te niekonfliktowe zmiany bo po akcepcie pierwszej zmiany kotek byłby zastapiony pieskiem, ale jesli zaakceptuje druga zmiane to juz z powrotem wrocimy do kotka bo to on byl w oryginalnym artykule.

Zrobie chyba tak jak @dzek69 sugeruje czyli zablokuje mozliwosc edytowania artykulu jesli juz sa jakies oczekujace zmiany. Wtedy react-diff-viewer powinen byc wystarczajacy czyli jakos sensownie podswietlilby mi te zmiany - nie znalazlem nic lepszego co madrze analizowaloby HTML.

Z innych zagwozdek: zalozmy ze artykul ma 3 strony typowego tekstu. Ktos zmienil jedno zdanie (poprawil literowke czy cos). Wowczas mimo drobnej zmiany, wciaz do bazy zapiswabym caly tekst czyli kolejne 3 strony tekstu. Nie znam sie bardzo na bazach danych wiec dopytam tutaj: jak bardzo to rozwiazanie moze byc w dluzszej perspektywie nieefektwne i doprowadzic do szybkiego wzrostu bazy danych? Zakladam ze moge po prostu przechowywac ostatnie np. 20 wersji artykulu ale jesl chcialbym przechowywac wszystkie to jak mozna to madrze zoptymalizowac? Dodam ze moja strona to bedzie malutki ulaek wikipedii - bedzie sie skupiac na konkretnej dziedzinie

1
Kokos123 napisał(a):

Z innych zagwozdek: zalozmy ze artykul ma 3 strony typowego tekstu. Ktos zmienil jedno zdanie (poprawil literowke czy cos). Wowczas mimo drobnej zmiany, wciaz do bazy zapiswabym caly tekst czyli kolejne 3 strony tekstu. Nie znam sie bardzo na bazach danych wiec dopytam tutaj: jak bardzo to rozwiazanie moze byc w dluzszej perspektywie nieefektwne i doprowadzic do szybkiego wzrostu bazy danych? Zakladam ze moge po prostu przechowywac ostatnie np. 20 wersji artykulu ale jesl chcialbym przechowywac wszystkie to jak mozna to madrze zoptymalizowac? Dodam ze moja strona to bedzie malutki ulaek wikipedii - bedzie sie skupiac na konkretnej dziedzinie

Po pierwsze, na potrzeby porównywania ich, i tak potrzebujesz dostać cały string.

Po drugie, bazy danych umieją operować podobnymi danymi "pod spodem".

Po trzecie, nawet jakbyś miał taki problem że baza danych nie umie utrzymać zbyt dużej ilości danych, to raczej to nie jest teraz, tylko za jakiś czas. Trzy strony tekstu to kilobajty. Prawdopodobnie przy milionie recordów, możliwe że więcej.

Po czwarte - nawet gdyby tak problem zaistniał (w co wątpię), to powinieneś go rozwiązać w sposób który minimalizuje komplikacje, np korzystając z dependency inversion.

Po piąte i najważniejsze - to głupota wprowadzać zmiany do prostego systemu "na wszelki wypadek", gdyby jakiś problem miał zaistnieć. Jak już mówiłem - YAGNI.

1 użytkowników online, w tym zalogowanych: 0, gości: 1