diff --git a/front/src/components/ShortcutsModal.vue b/front/src/components/ShortcutsModal.vue index 9bae0a9ca8f7823b66f4a6194b3b6883b1786716..e1c2a422c3a547d24f2509d90e27ff674f4011cb 100644 --- a/front/src/components/ShortcutsModal.vue +++ b/front/src/components/ShortcutsModal.vue @@ -5,7 +5,7 @@ </header> <section class="scrolling content"> <table - class="ui compact collapsing basic fixed single line table" + class="ui compact collapsing basic table" v-for="section in sections" :key="section.title"> <caption>{{ section.title }}</caption> diff --git a/front/src/components/audio/track/Row.vue b/front/src/components/audio/track/Row.vue index e3005c388a3604b471eeab895713fdd44f7782ad..e48de8e51796c2d40a2ddeb6e18fbf00e7bf2cf0 100644 --- a/front/src/components/audio/track/Row.vue +++ b/front/src/components/audio/track/Row.vue @@ -40,7 +40,7 @@ <td colspan="4" v-else> <translate :translate-context="'*/*/*'">N/A</translate> </td> - <td colspan="2"> + <td colspan="2" class="align right"> <track-favorite-icon class="favorite-icon" :track="track"></track-favorite-icon> <track-playlist-icon v-if="$store.state.auth.authenticated" diff --git a/front/src/components/audio/track/Table.vue b/front/src/components/audio/track/Table.vue index 1134e88a8ae04dfbcde68abeba59546bc46bc6c4..910d8f98aa0716521a04b45525763923527e1fdd 100644 --- a/front/src/components/audio/track/Table.vue +++ b/front/src/components/audio/track/Table.vue @@ -1,26 +1,28 @@ <template> - <table class="ui compact very basic fixed single line unstackable table"> - <thead> - <tr> - <th></th> - <th></th> - <th colspan="6"><translate :translate-context="'Content/Track/Table.Label'">Title</translate></th> - <th colspan="4"><translate :translate-context="'Content/Track/Table.Label'">Artist</translate></th> - <th colspan="4"><translate :translate-context="'Content/Track/Table.Label'">Album</translate></th> - <th colspan="4"><translate :translate-context="'Content/Track/Table.Label'">Duration</translate></th> - <th colspan="2"></th> - </tr> - </thead> - <tbody> - <track-row - :playable="playable" - :display-position="displayPosition" - :track="track" - :artist="artist" - :key="index + '-' + track.id" - v-for="(track, index) in tracks"></track-row> - </tbody> - </table> + <div class="table-wrapper"> + <table class="ui compact very basic unstackable table"> + <thead> + <tr> + <th></th> + <th></th> + <th colspan="6"><translate :translate-context="'Content/Track/Table.Label'">Title</translate></th> + <th colspan="4"><translate :translate-context="'Content/Track/Table.Label'">Artist</translate></th> + <th colspan="4"><translate :translate-context="'Content/Track/Table.Label'">Album</translate></th> + <th colspan="4"><translate :translate-context="'Content/Track/Table.Label'">Duration</translate></th> + <th colspan="2"></th> + </tr> + </thead> + <tbody> + <track-row + :playable="playable" + :display-position="displayPosition" + :track="track" + :artist="artist" + :key="index + '-' + track.id" + v-for="(track, index) in tracks"></track-row> + </tbody> + </table> + </div> </template> <script> diff --git a/front/src/components/auth/Settings.vue b/front/src/components/auth/Settings.vue index 3098d43f7d649aa895002fc697173b7e1104dbb7..f7c67109140d4be60f0a14e55bbe72fa9efaff77 100644 --- a/front/src/components/auth/Settings.vue +++ b/front/src/components/auth/Settings.vue @@ -128,7 +128,7 @@ <h3 class="ui header"> <translate>Hidden artists</translate> </h3> - <table class="ui compact very basic fixed single line unstackable table"> + <table class="ui compact very basic unstackable table"> <thead> <tr> <th><translate :translate-context="'Content/*/Table.Label'">Name</translate></th> diff --git a/front/src/components/common/ActionTable.vue b/front/src/components/common/ActionTable.vue index 10d49018b2a77e4cd188f48e2641fb83ca189a2e..f6143e0a32029e427ac1c6b41891e62d094e18c8 100644 --- a/front/src/components/common/ActionTable.vue +++ b/front/src/components/common/ActionTable.vue @@ -1,142 +1,144 @@ <template> - <table class="ui compact very basic single line unstackable table"> - <thead> - <tr> - <th colspan="1000"> - <div v-if="refreshable" class="right floated"> - <span v-if="needsRefresh"> - <translate :translate-context="'Content/*/Button.Help text.Paragraph'">Content have been updated, click refresh to see up-to-date content</translate> - </span> - <button - @click="$emit('refresh')" - class="ui basic icon button" - :title="labels.refresh" - :aria-label="labels.refresh"> - <i class="refresh icon"></i> - </button> - </div> + <div class="table-wrapper"> + <table class="ui compact very basic unstackable table"> + <thead> + <tr> + <th colspan="1000"> + <div v-if="refreshable" class="right floated"> + <span v-if="needsRefresh"> + <translate :translate-context="'Content/*/Button.Help text.Paragraph'">Content have been updated, click refresh to see up-to-date content</translate> + </span> + <button + @click="$emit('refresh')" + class="ui basic icon button" + :title="labels.refresh" + :aria-label="labels.refresh"> + <i class="refresh icon"></i> + </button> + </div> - <div class="ui small left floated form" v-if="actionUrl && actions.length > 0"> - <div class="ui inline fields"> - <div class="field"> - <label><translate :translate-context="'Content/*/Dropdown.Label/Noun'">Actions</translate></label> - <select class="ui dropdown" v-model="currentActionName"> - <option v-for="action in actions" :value="action.name"> - {{ action.label }} - </option> - </select> + <div class="ui small left floated form" v-if="actionUrl && actions.length > 0"> + <div class="ui inline fields"> + <div class="field"> + <label><translate :translate-context="'Content/*/Dropdown.Label/Noun'">Actions</translate></label> + <select class="ui dropdown" v-model="currentActionName"> + <option v-for="action in actions" :value="action.name"> + {{ action.label }} + </option> + </select> + </div> + <div class="field"> + <dangerous-button + v-if="selectAll || currentAction.isDangerous" :class="['ui', {disabled: checked.length === 0}, {'loading': actionLoading}, 'button']" + confirm-color="green" + color="" + @confirm="launchAction"> + <translate :translate-context="'Content/*/Button.Label/Short, Verb'">Go</translate> + <p slot="modal-header"> + <translate :translate-context="'Modal/*/Title'" + key="1" + :translate-n="affectedObjectsCount" + :translate-params="{count: affectedObjectsCount, action: currentActionName}" + translate-plural="Do you want to launch %{ action } on %{ count } elements?"> + Do you want to launch %{ action } on %{ count } element? + </translate> + </p> + <p slot="modal-content"> + <translate :translate-context="'Modal/*/Paragraph'">This may affect a lot of elements or have irreversible consequences, please double check this is really what you want.</translate> + </p> + <div slot="modal-confirm"><translate :translate-context="'Modal/*/Button.Label/Short, Verb'">Launch</translate></div> + </dangerous-button> + <div + v-else + @click="launchAction" + :disabled="checked.length === 0" + :class="['ui', {disabled: checked.length === 0}, {'loading': actionLoading}, 'button']"> + <translate :translate-context="'Content/*/Button.Label/Short, Verb'">Go</translate></div> + </div> + <div class="count field"> + <translate :translate-context="'Content/*/Paragraph'" + tag="span" + v-if="selectAll" + key="1" + :translate-n="objectsData.count" + :translate-params="{count: objectsData.count, total: objectsData.count}" + translate-plural="All %{ count } elements selected"> + All %{ count } element selected + </translate> + <translate :translate-context="'Content/*/Paragraph'" + tag="span" + v-else + key="2" + :translate-n="checked.length" + :translate-params="{count: checked.length, total: objectsData.count}" + translate-plural="%{ count } on %{ total } selected"> + %{ count } on %{ total } selected + </translate> + <template v-if="currentAction.allowAll && checkable.length > 0 && checkable.length === checked.length"> + <a @click="selectAll = true" v-if="!selectAll"> + <translate :translate-context="'Content/*/Link/Verb'" + key="3" + :translate-n="objectsData.count" + :translate-params="{total: objectsData.count}" + translate-plural="Select all %{ total } elements"> + Select all %{ total } elements + </translate> + </a> + <a @click="selectAll = false" v-else> + <translate :translate-context="'Content/*/Link/Verb'" key="4">Select only current page</translate> + </a> + </template> + </div> </div> - <div class="field"> - <dangerous-button - v-if="selectAll || currentAction.isDangerous" :class="['ui', {disabled: checked.length === 0}, {'loading': actionLoading}, 'button']" - confirm-color="green" - color="" - @confirm="launchAction"> - <translate :translate-context="'Content/*/Button.Label/Short, Verb'">Go</translate> - <p slot="modal-header"> - <translate :translate-context="'Modal/*/Title'" - key="1" - :translate-n="affectedObjectsCount" - :translate-params="{count: affectedObjectsCount, action: currentActionName}" - translate-plural="Do you want to launch %{ action } on %{ count } elements?"> - Do you want to launch %{ action } on %{ count } element? - </translate> - </p> - <p slot="modal-content"> - <translate :translate-context="'Modal/*/Paragraph'">This may affect a lot of elements or have irreversible consequences, please double check this is really what you want.</translate> - </p> - <div slot="modal-confirm"><translate :translate-context="'Modal/*/Button.Label/Short, Verb'">Launch</translate></div> - </dangerous-button> - <div - v-else - @click="launchAction" - :disabled="checked.length === 0" - :class="['ui', {disabled: checked.length === 0}, {'loading': actionLoading}, 'button']"> - <translate :translate-context="'Content/*/Button.Label/Short, Verb'">Go</translate></div> + <div v-if="actionErrors.length > 0" class="ui negative message"> + <div class="header"><translate :translate-context="'Content/*/Error message/Header'">Error while applying action</translate></div> + <ul class="list"> + <li v-for="error in actionErrors">{{ error }}</li> + </ul> </div> - <div class="count field"> - <translate :translate-context="'Content/*/Paragraph'" - tag="span" - v-if="selectAll" - key="1" - :translate-n="objectsData.count" - :translate-params="{count: objectsData.count, total: objectsData.count}" - translate-plural="All %{ count } elements selected"> - All %{ count } element selected - </translate> - <translate :translate-context="'Content/*/Paragraph'" - tag="span" - v-else - key="2" - :translate-n="checked.length" - :translate-params="{count: checked.length, total: objectsData.count}" - translate-plural="%{ count } on %{ total } selected"> - %{ count } on %{ total } selected - </translate> - <template v-if="currentAction.allowAll && checkable.length > 0 && checkable.length === checked.length"> - <a @click="selectAll = true" v-if="!selectAll"> - <translate :translate-context="'Content/*/Link/Verb'" - key="3" - :translate-n="objectsData.count" - :translate-params="{total: objectsData.count}" - translate-plural="Select all %{ total } elements"> - Select all %{ total } elements - </translate> - </a> - <a @click="selectAll = false" v-else> - <translate :translate-context="'Content/*/Link/Verb'" key="4">Select only current page</translate> - </a> - </template> + <div v-if="actionResult" class="ui positive message"> + <p> + <translate :translate-context="'Content/*/Paragraph'" + :translate-n="actionResult.updated" + :translate-params="{count: actionResult.updated, action: actionResult.action}" + translate-plural="Action %{ action } was launched successfully on %{ count } elements"> + Action %{ action } was launched successfully on %{ count } element + </translate> + </p> + + <slot name="action-success-footer" :result="actionResult"> + </slot> </div> </div> - <div v-if="actionErrors.length > 0" class="ui negative message"> - <div class="header"><translate :translate-context="'Content/*/Error message/Header'">Error while applying action</translate></div> - <ul class="list"> - <li v-for="error in actionErrors">{{ error }}</li> - </ul> - </div> - <div v-if="actionResult" class="ui positive message"> - <p> - <translate :translate-context="'Content/*/Paragraph'" - :translate-n="actionResult.updated" - :translate-params="{count: actionResult.updated, action: actionResult.action}" - translate-plural="Action %{ action } was launched successfully on %{ count } elements"> - Action %{ action } was launched successfully on %{ count } element - </translate> - </p> - - <slot name="action-success-footer" :result="actionResult"> - </slot> + </th> + </tr> + <tr> + <th v-if="actions.length > 0"> + <div class="ui checkbox"> + <input + type="checkbox" + @change="toggleCheckAll" + :disabled="checkable.length === 0" + :checked="checkable.length > 0 && checked.length === checkable.length"><label> </label> </div> - </div> - </th> - </tr> - <tr> - <th v-if="actions.length > 0"> - <div class="ui checkbox"> + </th> + <slot name="header-cells"></slot> + </tr> + </thead> + <tbody v-if="objectsData.count > 0"> + <tr v-for="(obj, index) in objects"> + <td v-if="actions.length > 0" class="collapsing"> <input type="checkbox" - @change="toggleCheckAll" - :disabled="checkable.length === 0" - :checked="checkable.length > 0 && checked.length === checkable.length"><label> </label> - </div> - </th> - <slot name="header-cells"></slot> - </tr> - </thead> - <tbody v-if="objectsData.count > 0"> - <tr v-for="(obj, index) in objects"> - <td v-if="actions.length > 0" class="collapsing"> - <input - type="checkbox" - :disabled="checkable.indexOf(getId(obj)) === -1" - @click="toggleCheck($event, getId(obj), index)" - :checked="checked.indexOf(getId(obj)) > -1"><label> </label> - </td> - <slot name="row-cells" :obj="obj"></slot> - </tr> - </tbody> - </table> + :disabled="checkable.indexOf(getId(obj)) === -1" + @click="toggleCheck($event, getId(obj), index)" + :checked="checked.indexOf(getId(obj)) > -1"><label> </label> + </td> + <slot name="row-cells" :obj="obj"></slot> + </tr> + </tbody> + </table> + </div> </template> <script> import axios from 'axios' diff --git a/front/src/components/library/FileUpload.vue b/front/src/components/library/FileUpload.vue index ec5e0dd23ea1cb30ca3aa25e197f558fe09a5640..09297caec33e9756062d48fdbfe7bf3652e5b706 100644 --- a/front/src/components/library/FileUpload.vue +++ b/front/src/components/library/FileUpload.vue @@ -79,39 +79,42 @@ <i><translate :translate-context="'Content/Library/Paragraph'" :translate-params="{extensions: supportedExtensions.join(', ')}">Supported extensions: %{ extensions }</translate></i> </file-upload-widget> </div> - <table v-if="files.length > 0" class="ui single line table"> - <thead> - <tr> - <th><translate :translate-context="'Content/Library/Table.Label'">Filename</translate></th> - <th><translate :translate-context="'Content/Library/Table.Label'">Size</translate></th> - <th><translate :translate-context="'Content/Library/Table.Label'">Status</translate></th> - </tr> - </thead> - <tbody> - <tr v-for="(file, index) in sortedFiles" :key="file.id"> - <td :title="file.name">{{ file.name | truncate(60) }}</td> - <td>{{ file.size | humanSize }}</td> - <td> - <span v-if="file.error" class="ui tooltip" :data-tooltip="labels.tooltips[file.error]"> - <span class="ui red icon label"> - <i class="question circle outline icon" /> {{ file.error }} + <div v-if="files.length > 0" class="table-wrapper"> + <div class="ui hidden divider"></div> + <table class="ui unstackable table"> + <thead> + <tr> + <th><translate :translate-context="'Content/Library/Table.Label'">Filename</translate></th> + <th><translate :translate-context="'Content/Library/Table.Label'">Size</translate></th> + <th><translate :translate-context="'Content/Library/Table.Label'">Status</translate></th> + </tr> + </thead> + <tbody> + <tr v-for="(file, index) in sortedFiles" :key="file.id"> + <td :title="file.name">{{ file.name | truncate(60) }}</td> + <td>{{ file.size | humanSize }}</td> + <td> + <span v-if="file.error" class="ui tooltip" :data-tooltip="labels.tooltips[file.error]"> + <span class="ui red icon label"> + <i class="question circle outline icon" /> {{ file.error }} + </span> </span> - </span> - <span v-else-if="file.success" class="ui green label"> - <translate :translate-context="'Content/Library/Table'" key="1">Uploaded</translate> - </span> - <span v-else-if="file.active" class="ui yellow label"> - <translate :translate-context="'Content/Library/Table'" key="2">Uploading…</translate> - ({{ parseInt(file.progress) }}%) - </span> - <template v-else> - <span class="ui label"><translate :translate-context="'Content/Library/Table'" key="3">Pending</translate></span> - <button class="ui tiny basic red icon button" @click.prevent="$refs.upload.remove(file)"><i class="delete icon"></i></button> - </template> - </td> - </tr> - </tbody> - </table> + <span v-else-if="file.success" class="ui green label"> + <translate :translate-context="'Content/Library/Table'" key="1">Uploaded</translate> + </span> + <span v-else-if="file.active" class="ui yellow label"> + <translate :translate-context="'Content/Library/Table'" key="2">Uploading…</translate> + ({{ parseInt(file.progress) }}%) + </span> + <template v-else> + <span class="ui label"><translate :translate-context="'Content/Library/Table'" key="3">Pending</translate></span> + <button class="ui tiny basic red icon button" @click.prevent="$refs.upload.remove(file)"><i class="delete icon"></i></button> + </template> + </td> + </tr> + </tbody> + </table> + </div> </div> <div :class="['ui', 'bottom', 'attached', 'segment', {hidden: currentTab != 'processing'}]"> diff --git a/front/src/components/playlists/Editor.vue b/front/src/components/playlists/Editor.vue index eb533fd01c3d2d642e60ebaa21b710977380e83c..d558ed38f7b1a8d5ccca361a9acb85b80e7c465a 100644 --- a/front/src/components/playlists/Editor.vue +++ b/front/src/components/playlists/Editor.vue @@ -48,24 +48,27 @@ <div class="ui hidden divider"></div> <template v-if="plts.length > 0"> <p><translate :translate-context="'Content/Playlist/Paragraph/Call to action'">Drag and drop rows to reorder tracks in the playlist</translate></p> - <table class="ui compact very basic fixed single line unstackable table"> - <draggable v-model="plts" element="tbody" @update="reorder"> - <tr v-for="(plt, index) in plts" :key="plt.id"> - <td class="left aligned">{{ plt.index + 1}}</td> - <td class="center aligned"> - <img class="ui mini image" v-if="plt.track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](plt.track.album.cover.small_square_crop)"> - <img class="ui mini image" v-else src="../../assets/audio/default-cover.png"> - </td> - <td colspan="4"> - <strong>{{ plt.track.title }}</strong><br /> - {{ plt.track.artist.name }} - </td> - <td class="right aligned"> - <i @click.stop="removePlt(index)" class="circular red trash icon"></i> - </td> - </tr> - </draggable> - </table> + <div class="table-wrapper"> + <table class="ui compact very basic unstackable table"> + <draggable v-model="plts" element="tbody" @update="reorder"> + <tr v-for="(plt, index) in plts" :key="plt.id"> + <td class="left aligned">{{ plt.index + 1}}</td> + <td class="center aligned"> + <img class="ui mini image" v-if="plt.track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](plt.track.album.cover.small_square_crop)"> + <img class="ui mini image" v-else src="../../assets/audio/default-cover.png"> + </td> + <td colspan="4"> + <strong>{{ plt.track.title }}</strong><br /> + {{ plt.track.artist.name }} + </td> + <td class="right aligned"> + <i @click.stop="removePlt(index)" class="circular red trash icon"></i> + </td> + </tr> + </draggable> + </table> + + </div> </template> </div> </div> diff --git a/front/src/style/_main.scss b/front/src/style/_main.scss index 55e23f320c82cd2205d8abcaef4f900252a172f0..7dda3b26475eb25ea638ab72e79fdcb532a93184 100644 --- a/front/src/style/_main.scss +++ b/front/src/style/_main.scss @@ -285,3 +285,19 @@ span.diff.added { span.diff.removed { background-color: rgba(255, 0, 0, 0.25); } + +.table-wrapper { + display: block; + overflow-x: auto; +} + +td.align.right { + text-align: right; +} + +.ui.pagination.menu { + margin-top: 1em; + + span { + margin-left: 1em; + } +}