directus / v8-archive

Directus Database API — Wraps Custom SQL Databases with a REST/GraphQL API
https://docs.directus.io/api/reference.html
505 stars 204 forks source link

"Rating" field does not allow more than 1 star + other #2250

Open asitemade4u opened 4 years ago

asitemade4u commented 4 years ago

Bug Report

The Rating field does not work any longer.

Steps to Reproduce

  1. create a new Rating field, full width, choose random color
  2. Max Stars = 3
  3. First issue: the Display field cannot be input
  4. Save
  5. When in the record itself, only one star is displayed and can be input.

Screenshot-20200326-183217 Screenshot-20200326-183225

Expected Behavior

  1. being able to select a range of stars, eg. 1-3
  2. being able to select multiple stars in the frontend

Actual Behavior

See above.

Environment:

jonasmeier1212 commented 4 years ago

I think I have found the reason for this behaviour, but I don't know exactly how to fix it.

In the component interfaces/rating/stars.vue the number of stars is rendered with this piece of code:

<button
    v-for="n in options.max_stars"
    :key="`star_${n}`"
    :class="ratingClass(n)"
    :style="ratingStyle(n)"
    :v-tooltip="n"
    @mouseenter="readonly ? '' : (hovered = n)"
    @mouseleave="readonly ? '' : (hovered = null)"
    @click="readonly ? '' : set(n)"
></button>

This syntax for v-for requires the second parameter to be an integer. But it is saved as a string in the database, so there is only one star displayed.

In the table directus_fields an field with interface rating has the following value in the options row: {"active_color":"amber","max_stars":"3","display":"star"} However it should be: {"active_color":"amber","max_stars":3,"display":"star"}

In the former case the max_stars key is interpreted as string which results in the unexpected behaviour.

Now my guess is, that the solution would be to set these options correctly. For this I debugged the collection settings page and found out the following: The value comes from VInput and is passed down to VExtInput and from there it is send to the server without any modification. The VInput component grabs the value of the input field with the following code: (event.target as HTMLInputElement).value // v-input.vue Line 73 But even if the HTML input element is set to type="number", this will always be a string!

So a solution would be to convert all HTMLInputElement values which should be a number to a number. This could be done directly in the v-input.vue component, but I don't know if this would cause any unwanted side effect.

benhaynes commented 4 years ago

Thanks @jonasmeier1212! Any thoughts on this @rijkvanzanten ?

rijkvanzanten commented 4 years ago

@jonasmeier1212 a quick fix would be to cast the max_stars option to a number before using it here:

v-for="n in +options.max_stars"

jonasmeier1212 commented 4 years ago

@rijkvanzanten Thanks, that should do the trick! But is it the correct solution? Wouldn't it be better to store this value with the right type? If you give me a hint, where and in which way this error can be fixed, I'll do it and open a PR.