Bug 30225 - Rewrite cities admin view in Vue
Summary: Rewrite cities admin view in Vue
Status: In Discussion
Alias: None
Product: Koha
Classification: Unclassified
Component: Architecture, internals, and plumbing (show other bugs)
Version: unspecified
Hardware: All All
: P5 - low enhancement
Assignee: Jonathan Druart
QA Contact: Testopia
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-03-04 10:20 UTC by Jonathan Druart
Modified: 2022-10-17 08:48 UTC (History)
5 users (show)

See Also:
Change sponsored?: ---
Patch complexity: ---
Documentation contact:
Documentation submission:
Text to go in the release notes:
Version(s) released in:
Circulation function:


Attachments
Bug 30225: Rewrite cities admin view in Vue (31.23 KB, patch)
2022-03-04 10:48 UTC, Jonathan Druart
Details | Diff | Splinter Review
Bug 30225: Fix edit>cancel>list>add (950 bytes, patch)
2022-03-08 17:00 UTC, Jonathan Druart
Details | Diff | Splinter Review
Bug 30225: Rewrite cities admin view in Vue (33.07 KB, patch)
2022-03-09 13:34 UTC, Jonathan Druart
Details | Diff | Splinter Review
Bug 30225: Rewrite cities admin view in Vue (33.07 KB, patch)
2022-03-30 14:24 UTC, Tomás Cohen Arazi (tcohen)
Details | Diff | Splinter Review
Bug 30225: Rewrite cities admin view in Vue (33.15 KB, patch)
2022-09-06 16:33 UTC, Slava Shishkin
Details | Diff | Splinter Review

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Druart 2022-03-04 10:20:54 UTC
Same as bug 30160 but using Vue 3
Comment 1 Jonathan Druart 2022-03-04 10:48:51 UTC
Created attachment 131371 [details] [review]
Bug 30225: Rewrite cities admin view in Vue

Same as bug 30160 but using Vue 3 (https://vuejs.org/).

TODO:
* Use Vue Router and remove the switch-view weirdness
* Clean package.json it contains too many things

Notes:
* Use of webpack instead of gulp (didn't manage to make it work, and
webpack seems the "new standard"?)
* Cannot fully use vue-boostrap-3 as it is using bootstrap 4 and
conflict with our version (3.5). The add form for instance should
display label and input inline with the code used in this patch, but
it's not displayed correctly
* Using bootstrap-vue-3 as bootstrap-vue is still for Vue 2

To improve/weirdness:
* The fetch before the edit and delete is done too late, in created().
You can notice a "blink".
But lifecycle hooks don't permit a await here
https://vuejs.org/guide/essentials/lifecycle.html
* I guess we should have the whole model stored in Vue to take full
advantage of its functionalities
* We need to inject the "Edit" and "Delete" buttons, it was a nightmare
and it's not done properly. I didn't manage to render a component that
is using the font-awesome-icon and bootstrap styles.

Hot reload using `yarn watch_js`
Comment 2 Kyle M Hall (khall) 2022-03-04 17:05:42 UTC
This looks really interesting!

Jonathan, having used both to implement the same feature, I would love to know your opinion on how easy each one was to learn, and to use.
Comment 3 Jonathan Druart 2022-03-07 11:58:33 UTC
(In reply to Kyle M Hall from comment #2)
> This looks really interesting!
> 
> Jonathan, having used both to implement the same feature, I would love to
> know your opinion on how easy each one was to learn, and to use.

Good question.
I should start by saying that I had almost no expression with any of JS frameworks. Only played a bit with react a couple of months ago.
I am at a loss when diving into the whole node ecosystem: npm, yarn, gulp, and all the transpilers/compilers available. It took me a while to make it work with Vue...

It seems very easy to start a new project from scratch using any of the JS frameworks, you have several CLI tools (Vue CLI, create-react-app) to build the whole structure of the project, run a dev instance on a port, hot reload, etc. But there is way less documentation when you want to integrate them to an existing project, write your own code to transpile, etc.

Anyway, I found react and vue quite different.
The major problems I had to deal with were:
1. The integration with DataTables
  Both React/Vue and DataTables will manage the DOM and we should not make DT mess with React/Vue's components. Actually we should not make React/Vue aware of DT's instance
2. Render React/Vue's components "on the fly", for the "Edit" and "Delete" buttons we had to each action cell
  On need to make React/Vue aware of the onclick event to change the state of the app, but those components need to be added after DT has been initialized.

Given all the work we provided to make our DT implementation a big player of our REST API usage (and even when we don't use the REST API routes) I didn't feel confident to bypass it, we must deal with is as it, and not rewrite another version of the table (ideally the table should be a REST/Vue component).

Another problem was the different versions and the new coding styles/recommendations.
For react I learnt, after my first implementation, that everything was obsolete. They do no longer use class/this, but functions and hooks. Same for Vue, there is v3 that is "the new default version as of 7 February 2022" (that's fresh!) and so you find a lot of code that is actually v2.
Also, bootstrap's libraries (BootstrapVue and React-Bootstrap), BoostrapVue is supporting Vue2.7 so you need to use another BootstrapVue3 lib for Vue3, which is using Bootstrap 5, way ahead of our Bootstrap version 3.5 (and so buttons are either not styled correctly when using BootstrapVue3's tags, or the whole Koha CSS get broken when you use the BootstrapVue3 css).

I haven't answered your question yet, I can give you some subjective feeling:
Vue
Pro:
 * Template/Script/Style (I haven't used style in my implement however) pattern in the component. The templating system is great (see <template> in *.vue files)
Con:
 * Not much v3 examples available yet

React
Pro:
 * lot of examples found on the web
Con:
 * a bit more time to understand the whole picture

I didn't find how to implement a routing system correctly (click on "edit" button to display the edit form but modify the url, /cities/42?op=add_form).
It seems easier to implement in Vue.

Both are similar I would say, starting as a beginner I haven't found one easier/harder than the other. Both need the same convoluted contortions to deal with our existing project...
Comment 4 Kyle M Hall (khall) 2022-03-07 12:10:44 UTC
(In reply to Jonathan Druart from comment #3)

Thanks! That's great to know!

I don't know if we want to do this as a community, but it does looks like Vue.js can be used without webpack:
https://markus.oberlehner.net/blog/goodbye-webpack-building-vue-applications-without-webpack/
https://bestofvue.com/repo/arijs-vue-next-example-vuejs-examples
Comment 5 David Cook 2022-03-07 22:38:46 UTC
I'm looking forward to looking at this more (at some point).

I must've been using Vue 2 back in August 2020, but I did some very basic things similar to this:

<script src="https://npmcdn.com/vue/dist/vue.js"></script>

    <div id="app">
      <p>{{ message }}</p>
      <button v-on:click="reverseMessage">Reverse Message</button>
    </div>
[% MACRO jsinclude BLOCK %]
<script>
    new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue.js!'
      },
      methods: {
        reverseMessage: function () {
          this.message = this.message.split('').reverse().join('')
        }
      }
    })
</script>
[% END %]

--

I didn't go very far with Vue.js as I had other priorities, but it seemed easy to integrate with a legacy app. I imagine I was greatly under utilizing its power with this helloworld, but I liked how it didn't require anything complicated to use it.
Comment 6 Jonathan Druart 2022-03-08 17:00:59 UTC
Created attachment 131496 [details] [review]
Bug 30225: Fix edit>cancel>list>add

New form shouldn't be populated with last edited city. Appened when
cancel link was used
Comment 7 Jonathan Druart 2022-03-09 13:34:08 UTC
Created attachment 131523 [details] [review]
Bug 30225: Rewrite cities admin view in Vue

Same as bug 30160 but using Vue 3 (https://vuejs.org/).

TODO:
* Use Vue Router and remove the switch-view weirdness
* Clean package.json it contains too many things

Notes:
* Use of webpack instead of gulp (didn't manage to make it work, and
webpack seems the "new standard"?)
* Cannot fully use vue-boostrap-3 as it is using bootstrap 4 and
conflict with our version (3.5). The add form for instance should
display label and input inline with the code used in this patch, but
it's not displayed correctly
* Using bootstrap-vue-3 as bootstrap-vue is still for Vue 2

To improve/weirdness:
* The fetch before the edit and delete is done too late, in created().
You can notice a "blink".
But lifecycle hooks don't permit a await here
https://vuejs.org/guide/essentials/lifecycle.html
* I guess we should have the whole model stored in Vue to take full
advantage of its functionalities
* We need to inject the "Edit" and "Delete" buttons, it was a nightmare
and it's not done properly. I didn't manage to render a component that
is using the font-awesome-icon and bootstrap styles.

Hot reload using `yarn watch_js`

Bug 30225: Fix edit>cancel>list>add

New form shouldn't be populated with last edited city. Appened when
cancel link was used
Comment 8 Marcel de Rooy 2022-03-10 08:58:00 UTC
Couldnt resist posting these ones too here:

https://svelte.dev/

and

https://webassembly.org/
Comment 9 Kyle M Hall (khall) 2022-03-10 13:22:41 UTC
(In reply to Marcel de Rooy from comment #8)
> Couldnt resist posting these ones too here:
> 
> https://svelte.dev/
> 
> and
> 
> https://webassembly.org/

I do find Svelte to be a super interesting project, but I would never consider it for Koha. It's community is very small and integrating it with our workflow would be a challenge.

WebAssembly on the other hand isn't even a javascript framework, it's basically a way to compile non-javascript application code to a standard intermediary language. For example, I write some apps in C++/Qt6, and could in theory compile an application to webassembly ( Qt6 added wasm support ) so my formerly desktop-only application would now also be a web app!
Comment 10 Marcel de Rooy 2022-03-10 13:52:53 UTC
(In reply to Kyle M Hall from comment #9)

> I do find Svelte to be a super interesting project, but I would never
> consider it for Koha. It's community is very small and integrating it with
> our workflow would be a challenge.
> 
> WebAssembly on the other hand isn't even a javascript framework, it's
> basically a way to compile non-javascript application code to a standard
> intermediary language. For example, I write some apps in C++/Qt6, and could
> in theory compile an application to webassembly ( Qt6 added wasm support )
> so my formerly desktop-only application would now also be a web app!

Good points. Just widening the discussion a bit while seeing movements going away from Javascript which surely is 'future music' :)
Comment 11 Kyle M Hall (khall) 2022-03-10 14:18:23 UTC
> Good points. Just widening the discussion a bit while seeing movements going
> away from Javascript which surely is 'future music' :)

I'm looking forward to the day when we can replace our javascript with even more Perl ;)
Comment 12 Tomás Cohen Arazi (tcohen) 2022-03-30 14:24:34 UTC Comment hidden (obsolete)
Comment 13 David Cook 2022-04-07 13:03:37 UTC
My test plan:
1. yarn install
2. yarn build_js
3. http://localhost:8081/cgi-bin/koha/admin/cities.pl

UI Feedback:
1. Overall, the UI is looking pretty good!
2. On http://localhost:8081/cgi-bin/koha/admin/cities.pl, the "Loading..." word should probably be in the centre, so that it's a smoother transition to "There are no cities defined"
3. Adding a new city, the HTML could be styled more nicely (shorter input boxes, input boxes next to labels - so they're not as disjointed, maybe leaving off "City" from all the placeholders), but it works. 
4. The datatable on http://localhost:8081/cgi-bin/koha/admin/cities.pl looks pretty good and the filters work
5. However, the "City created" message hangs around too long. It still shows while I'm interacting with the data table, and that feels awkward.
6. When I click on "Edit", the template momentarily says "New city" before switching to "Edit city", which is jarring. I don't know what's happening in the code, but an easy workaround would be to hide the form with CSS until after it's fully rendered.
7. Delete city works, although it could also be styled more nicely.

In summary, I think the functionality is all there, but it just needs some aesthetic polishing I think.

Code Feedback:
1. I'm not familiar with Vue 3, so I think I'll need to study it more. 
2. I think we could probably remove more of cities.tt if I understand correctly since I don't think it's used anymore. 
3. This would be a good candidate for Bug 30289 I think. Could use the WRAPPER to create the bulk of the page, and then have the Vue app in the main section...
4. I like the idea of changing from http://localhost:8081/cgi-bin/koha/admin/cities.pl to something like http://localhost:8081/cgi-bin/koha/admin#cities and then using a router 
5. While I don't know Vue 3, I keep thinking we should be able to create more generic CRUD templates. I think one of the great downsides of Koha at the moment is having too many different CRUD forms. This looks interesting: https://vuejsdevelopers.com/2017/06/11/vue-js-extending-components/

In summary, I think this is on the right track, but I think it needs more polishing as well. 

I could have a crack at making some more generic components... although I'm not sure when...
Comment 14 Slava Shishkin 2022-09-06 16:33:17 UTC
Created attachment 140235 [details] [review]
Bug 30225: Rewrite cities admin view in Vue

Same as bug 30160 but using Vue 3 (https://vuejs.org/).

TODO:
* Use Vue Router and remove the switch-view weirdness
* Clean package.json it contains too many things

Notes:
* Use of webpack instead of gulp (didn't manage to make it work, and
webpack seems the "new standard"?)
* Cannot fully use vue-boostrap-3 as it is using bootstrap 4 and
conflict with our version (3.5). The add form for instance should
display label and input inline with the code used in this patch, but
it's not displayed correctly
* Using bootstrap-vue-3 as bootstrap-vue is still for Vue 2

To improve/weirdness:
* The fetch before the edit and delete is done too late, in created().
You can notice a "blink".
But lifecycle hooks don't permit a await here
https://vuejs.org/guide/essentials/lifecycle.html
* I guess we should have the whole model stored in Vue to take full
advantage of its functionalities
* We need to inject the "Edit" and "Delete" buttons, it was a nightmare
and it's not done properly. I didn't manage to render a component that
is using the font-awesome-icon and bootstrap styles.

Hot reload using `yarn watch_js`

Bug 30225: Fix edit>cancel>list>add

New form shouldn't be populated with last edited city. Appened when
cancel link was used
Comment 15 Slava Shishkin 2022-09-06 16:37:11 UTC
Rebased to the latest master. Conflict was because columns_settings now table_settings.
Comment 16 Jonathan Druart 2022-10-17 08:48:24 UTC
Hum, the ERM code diverged a lot from this. This was supposed to get attention several months ago, now people should focus on ERM.

This bug is still valid and the patch can be seen as a quick overview of Vue, and to see it live in Koha. But this patch cannot be pushed to master as it.