Problem z przenoszeniem stron w Kompendium – długa lista

0

Problem

Jako Moderator Wiki mam możliwość przenoszenia stron w Kompendium (z tego, co pamiętam, ta funkcja nie jest dostępna dla zwykłych użytkowników). Jest to realizowane za pomocą specjalnej strony, na której jest kontrolka z listą możliwych "nadstron" (?). Jednak z racji tego, że lista zawiera chyba wszystkie strony z Kompendium, znalezienie odpowiedniej pozycji na niej jest trudne. Raz, że pozycji jest bardzo dużo, a dwa, że nawet podczas samego przewijania listy obserwuję u siebie lagi spowolnienie działania przeglądarki.

Zachowanie aktualne

Lista możliwych "nadstron" zawiera wszystkie (?) strony z Kompendium.

Zachowanie oczekiwane

Lista możliwych "nadstron" zawiera jakiś podzbiór stron z Kompendium. Ewentualnie zamiast jednej listy są dwie listy, jedna zawierająca strony poziomów 1 i 2, a druga strony poziomów od 3 w górę dla wybranego danego poziomu na pierwszej liście (wybór poziomów tak ustaliłem, żeby jakoś równomiernie rozłożyć liczbę stron w obu listach).


UPDATE

@Adam Boduch, czy dobrze myślę, że wypełnianie tej listy jest wykonywane przez tę funkcję? (Pomijam ciąg wywołań do niej prowadzący). Zamieszczę ją poniżej:

    public function treeList()
    {
        $this->applyCriteria();


        $result = [];
        $data = $this->model->from($this->rawFunction('wiki_children'))->get(['id', 'title', 'depth']);


        foreach ($data as $row) {
            $result[$row['id']] = str_repeat(' ', $row['depth'] * 4) . $row['title'];
        }


        return $result;
    }

UPDATE 2

@Adam Boduch, czy dobrze myślę, że wystarczy powyższą funkcję zmienić w ten sposób?

    public function treeList()
    {
        $this->applyCriteria();


        $result = [];
        $data = $this->model->from($this->rawFunction('wiki_children'))->get(['id', 'title', 'depth']);


        foreach ($data as $row) {
            if ($row['depth'] <= 2) {
                $result[$row['id']] = str_repeat('&nbsp;', $row['depth'] * 4) . $row['title'];
            }
        }


        return $result;
    }

Nietestowane i nie znam się na PHP. Ale patrząc na PHP jako na pseudokod, to ta zmiana wydaje się robić wszystko, czego oczekiwałbym.


PS No nie, oczywiście, zapomniałem, że gdzieś pozostałe poziomy trzeba umieścić. <myśli>


UPDATE 3

To może tak? Będzie wymagać więcej zmian w kodzie wywołującym tę funkcję, ale na razie dla uproszczenia tylko to pokazuję.

    public function treeList()
    {
        $this->applyCriteria();


        $double_result = [[], []];
        $data = $this->model->from($this->rawFunction('wiki_children'))->get(['id', 'title', 'depth']);


        foreach ($data as $row) {
            if ($row['depth'] <= 2) {
                $double_result[0][$row['id']] = str_repeat('&nbsp;', $row['depth'] * 4) . $row['title'];
            } else {
                $double_result[1][$row['id']] = str_repeat('&nbsp;', $row['depth'] * 4) . $row['title'];
            }
        }


        return $double_result;
    }
0

Zgadzam się w 100% że taka prezentacja jest giga nieużyteczna. Czasem spędzam 1-3 minuty żeby tylko przenieść stronę. Dodatkowo jest wyświetlana w zwykłym <select> przez co nie można wyszukać nic po frazie, jedynie po pierwszej literze, a ponieważ są posortowane kategoriami to szukanie po jednej literze nie ma sensu.

Ja zamiast update'ować backend, to bym zupdateował widok, tak żeby dało się iść breadcrumbami, np

PHP -> Sql -> Sql Injection

a jeśli nie, to żeby chociaż dało się wyszukać w selectie po całej frazie - żeby to nie był głupi <select>.

1

HAha, może w drugiej kolejności zrobię komponent vue do przenoszenia stron :D

0

@TomRiddle: byłoby pewnie miło, ale może da się jednak szybciej zmienić parę linijek w dwóch-trzech istniejących funkcjach PHP. :P

1
Silv napisał(a):

@TomRiddle: byłoby pewnie miło, ale może da się jednak szybciej zmienić parę linijek w dwóch-trzech istniejących funkcjach PHP. :P

A jakie to ma znaczenie czy szybciej czy nie szybciej?

Trzeba zrobić tak żeby było dobrze.

0

Po przemyśleniu jednak to rozwiązanie zaproponowane w ostatnim listingu pierwszego postu jest co najmniej niesatysfakcjonujące. Nie działa, o ile nie zna się na pamięć wszystkich grup i podgrup Kompendium, żeby dopasować poziomy. Trzeba ostatecznie wymyślić coś, co pozwoli uzależnić jedną listę od drugiej.

Jeśli chodzi o sam design tego rozwiązania:

  1. Być może, @TomRiddle , masz rację, że można zmienić SQL. Choć nie rozumiem do końca, co napisałeś – mógłbyś rozwinąć?
  2. Ja mam sugestię, że ilość poziomów w Kompendium można by ograniczyć do trzech: grupy stron, podgrupy stron i strony. Ale nie wiem, @Adam Boduch, czy to nie zepsułoby jakiejś Twojej wizji designu Kompendium?

PS Tom, a propos Twoich słów "żeby było dobrze" – zgadzam się. :) Mierzę po prostu siły użytkowników 4p na zamiary.

0
Silv napisał(a):

Po przemyśleniu jednak to rozwiązanie zaproponowane w ostatnim listingu pierwszego postu jest co najmniej niesatysfakcjonujące. Nie działa, o ile nie zna się na pamięć wszystkich grup i podgrup Kompendium, żeby dopasować poziomy. Trzeba ostatecznie wymyślić coś, co pozwoli uzależnić jedną listę od drugiej.

Ale nie musisz ich znać, byłyby wpisane w kontrolce. Jak np widok folderów. Albo ewentualnie autocomplete w breadcrumbach.

0

Wyjaśnienie: mnie chodziło o to, że jeśli bezpardonowo rozdzieli się listy po prostu po parametrze poszczególnych pozycji (owa depth), to powstaną dwie niepowiązane ze sobą listy. I teraz jeśli się nie wie, która strona z listy nr 2 jest umieszczona jako podstrona danej strony z listy nr 1, czyli nie umie się dopasować tych stron po ich nazwach, to to rozwiązanie nie działa.


Może tak:

Funkcja treeList klasy WikiRepository, odpowiedzialna za wypełnianie listy stron na Wiki (o ile w ogóle dobrze ją zidentyfikowałem):

    public function treeList()
    {
        $this->applyCriteria();

        $combined_result = [];
        $id = -1; // TODO Czy $row['id'] może mieć wartości poniżej 0?
        $last_higher = -1; // TODO Czy $row['depth'] może mieć wartości poniżej 0?
        $data = $this->model->from($this->rawFunction('wiki_children'))->get(['id', 'title', 'depth']);

        foreach ($data as $row) {
            $combined_result[$row['id']] = [];
            $combined_result[$row['id']][0] = str_repeat('&nbsp;', $row['depth'] * 4) . $row['title'];

            if ($row['depth'] < $last_higher) {
                $combined_result[$row['id']][$id] = str_repeat('&nbsp;', $row['depth'] * 4) . $row['title'];
                $id = $id + 1;
            } else {
                $id = 1;
                $last_higher = $row['depth'];
            }
        }

        return $combined_result;
    }

Funkcja getTreeList traita (co to?) TreeListTrait, wywołująca powyższą funkcję treeList – bez zmian.

Funkcja buildForm klasy CloneForm, wywołująca powyższą funkcję getTreeList – bez zmian.

Funkcja buildForm klasy MoveForm, wywołująca powyższą funkcję buildForm – bez zmian.

Ale coś na pewno trzeba zmienić – tylko gdzie? Czy w interfejsie? Ale gdzie? Nie wiem, gdzie dalej szukać…


UPDATE

Po ciągu znaków choices znalazłem coś takiego:

{{ form_select(name ~ (attr.multiple is defined ? '[]'), (empty_value ? {'': empty_value} : {}) + choices, value, attr|merge({class: (attr.class|default('') ~  ' form-control' ~ (error ? ' is-invalid'))|trim})) }}

Ale jak tutaj zmienić wykorzystanie choices, żeby odpowiadało moim zmianom w funkcji treeList?


UPDATE 2

Bez sensu, znalazłem parę bugów kolących w oczy. Teraz powinno być lepiej:

    public function treeList()
    {
        $this->applyCriteria();

        $combined_result = [];
        $id = -1;
        $sub_id = -1;
        $last_higher = -1; // TODO Czy $row['depth'] może mieć wartości poniżej 0?
        $data = $this->model->from($this->rawFunction('wiki_children'))->get(['id', 'title', 'depth']);

        foreach ($data as $row) {
            if ($row['depth'] < $last_higher) {
                $combined_result[$id][$sub_id] = str_repeat('&nbsp;', $row['depth'] * 4) . $row['title'];
                $sub_id = $sub_id + 1;
            } else {
                $id = $id + 1;
                $combined_result[$id] = [];
                $combined_result[$id][0] = str_repeat('&nbsp;', $row['depth'] * 4) . $row['title'];
                $sub_id = 1;
                $last_higher = $row['depth'];
            }
        }

        return $combined_result;
    }

UPDATE 3 Bez sensu. Nawet nie poprawiam tego kodu powyżej, bo nie wiem, jak to zmienić, żeby było tak, jak chcę. Muszę pomyśleć…


UPDATE 4

Jeśli $row['depth'] jest większe niż 1, elementy listy $data są dołączane do takiego ostatniego elementu listy $combined_result, dla którego $row['depth'] było mniejsze lub równe 1. Jeśli nie, tworzony jest nowy element listy $combined_result. Nie wiem, czy $row['depth'] może przyjmować wartość 0 – jeśli tak, nie jestem pewien, czy wynik działania tej funkcji będzie poprawny.

    public function treeList()
    {
        $this->applyCriteria();

        $combined_result = [];
        $id = -1;
        $sub_id = -1;
        $last_higher = -1; // TODO Czy $row['depth'] może mieć wartości poniżej 0?
        $data = $this->model->from($this->rawFunction('wiki_children'))->get(['id', 'title', 'depth']);

        foreach ($data as $row) {
            if ($row['depth'] > 1) {
                $combined_result[$id][$sub_id] = str_repeat('&nbsp;', $row['depth'] * 4) . $row['title'];
                $sub_id = $sub_id + 1;
            } else {
                $id = $id + 1;
                $combined_result[$id] = [];
                $combined_result[$id][0] = str_repeat('&nbsp;', $row['depth'] * 4) . $row['title'];
                $sub_id = 1;
                $last_higher = $row['depth'];
            }
        }

        return $combined_result;
    }

UPDATE 5

Wyjaśnię może wizualnie, co chcę osiągnąć przez powyższą zmianę w kodzie.

  1. Tak obecnie wygląda formularz przenoszenia stron:

    screenshot-20211008015114.png

  2. Wyobrażam sobie, że po powyższej zmianie w kodzie formularz powinien wyglądać jak na poniższym zrzucie ekranu. Kontrolka o etykiecie "Nowa strona macierzysta – poziom 1" zawierałaby listę stron na najwyższym poziomie, czyli $combined_result[0][0], $combined_result[1][0] i tak dalej. I teraz: jeśli użytkownik nie wybrałby nic w tej kontrolce, to kontrolka o etykiecie "Nowa strona macierzysta – poziom 2" nie zawierałaby nic (może być jedna pozycja z tymi dwoma minusami reprezentująca to "nic"). Jeśli zaś użytkownik wybrałby jakąś pozycję na liście w tej kontrolce, o danym $id, to kontrolka o etykiecie "Nowa strona macierzysta – poziom 2" zawierałaby listę tych stron poziomu drugiego, które są podstronami strony z wybranej pozycji; prócz tego listę wszystkich stron, które są podstronami tych stron poziomu drugiego; i tak dalej, przez wszystkie poziomy; czyli $combined_result[$id][1], $combined_result[$id][2] i tak dalej.

    screenshot-20211008015406.png

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