Alerts
2 years ago
BoxActions
2 years ago
PaymentsPage
2 years ago
TableColumns
2 years ago
VuiBoxes
2 years ago
ActionsWithFilters.vue
2 years ago
ChooseAction.vue
2 years ago
ClearFiltersButton.vue
2 years ago
DetailsTableWithStore.vue
2 years ago
EntriesList.vue
2 years ago
EntriesTable.vue
2 years ago
EntriesTableSkeleton.vue
2 years ago
EntryColumnList.vue
2 years ago
EntryColumnsTable.vue
2 years ago
FormBuilderPage.vue
2 years ago
PageActions.vue
2 years ago
PostBoxContainer.vue
2 years ago
PostBoxGrid.vue
2 years ago
PostBoxSimple.vue
2 years ago
PostBoxSkeleton.vue
2 years ago
PostBoxTable.vue
2 years ago
SideBarBoxes.vue
2 years ago
TablePagination.vue
2 years ago
EntriesTableSkeleton.vue
360 lines
| 1 | <template> |
| 2 | <div :class="rootClasses"> |
| 3 | <cx-vui-list-table |
| 4 | :is-empty="! list.length" |
| 5 | :empty-message="emptyMessage" |
| 6 | > |
| 7 | <template #heading> |
| 8 | <cx-vui-list-table-heading |
| 9 | :slots="filteredColumns" |
| 10 | > |
| 11 | <span |
| 12 | :key="column" |
| 13 | :slot="column" |
| 14 | v-for="column in filteredColumns" |
| 15 | > |
| 16 | <template v-if="getHeadingComponent( column )"> |
| 17 | <keep-alive> |
| 18 | <component |
| 19 | v-bind:is="getHeadingComponent( column )" |
| 20 | :value="columns[ column ]" |
| 21 | :scope="scope" |
| 22 | /> |
| 23 | </keep-alive> |
| 24 | </template> |
| 25 | <template v-else> |
| 26 | {{ columns[ column ] ? columns[ column ].label : '' }} |
| 27 | </template> |
| 28 | <svg v-if="columns[ column ].sortable" width="10" |
| 29 | height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg"><path |
| 30 | d="M0.833374 0.333328L5.00004 4.5L9.16671 0.333328H0.833374Z" fill="#7B7E81"/></svg> |
| 31 | </span> |
| 32 | </cx-vui-list-table-heading> |
| 33 | </template> |
| 34 | <template #footer v-if="footerHeading"> |
| 35 | <cx-vui-list-table-heading |
| 36 | :slots="filteredColumns" |
| 37 | > |
| 38 | <span |
| 39 | :key="column" |
| 40 | :slot="column" |
| 41 | v-for="column in filteredColumns" |
| 42 | > |
| 43 | <template v-if="getHeadingComponent( column )"> |
| 44 | <keep-alive> |
| 45 | <component |
| 46 | v-bind:is="getHeadingComponent( column )" |
| 47 | :value="columns[ column ]" |
| 48 | :scope="scope" |
| 49 | /> |
| 50 | </keep-alive> |
| 51 | </template> |
| 52 | <template v-else> |
| 53 | {{ columns[ column ] ? columns[ column ].label : '' }} |
| 54 | </template> |
| 55 | <svg v-if="columns[ column ].sortable" width="10" |
| 56 | height="5" viewBox="0 0 10 5" fill="none" xmlns="http://www.w3.org/2000/svg"><path |
| 57 | d="M0.833374 0.333328L5.00004 4.5L9.16671 0.333328H0.833374Z" fill="#7B7E81"/></svg> |
| 58 | </span> |
| 59 | </cx-vui-list-table-heading> |
| 60 | </template> |
| 61 | <template #items> |
| 62 | <div |
| 63 | v-for="( entry, entryID ) in list" |
| 64 | :key="entryID" |
| 65 | :class="classEntry( entryID, entry )" |
| 66 | > |
| 67 | <div class="list-table-item-columns"> |
| 68 | <EntryColumnsTable |
| 69 | v-for="column in filteredColumns" |
| 70 | :key="'entry_' + column" |
| 71 | :column="column" |
| 72 | :entry="entry" |
| 73 | :entry-id="entryID" |
| 74 | :scope="scope" |
| 75 | :columns-components="columnsComponents" |
| 76 | /> |
| 77 | </div> |
| 78 | <div class="list-table-item-actions" v-if="entry.actions"> |
| 79 | <span |
| 80 | v-for="action in entry.actions.value" |
| 81 | :key="action.value" |
| 82 | > |
| 83 | <a |
| 84 | :href="getActionHref( action )" |
| 85 | :class="getActionClass( action )" |
| 86 | @click="onClickAction( action, entry, $event )" |
| 87 | > |
| 88 | {{ action.label }} |
| 89 | </a> |
| 90 | </span> |
| 91 | </div> |
| 92 | </div> |
| 93 | </template> |
| 94 | </cx-vui-list-table> |
| 95 | </div> |
| 96 | </template> |
| 97 | |
| 98 | <script> |
| 99 | import Constants from '../constants'; |
| 100 | import ScopePropMixin from '../mixins/ScopeStoreMixin'; |
| 101 | import GetColumnComponent from '../mixins/GetColumnComponent'; |
| 102 | import EntryColumnsTable from './EntryColumnsTable'; |
| 103 | import { getPrimaryId } from '../functions'; |
| 104 | |
| 105 | const { |
| 106 | CHOOSE_ACTION, |
| 107 | CLICK_ACTION, |
| 108 | } = Constants; |
| 109 | |
| 110 | const { |
| 111 | mapState, |
| 112 | mapGetters, |
| 113 | mapActions, |
| 114 | mapMutations, |
| 115 | } = window.Vuex; |
| 116 | |
| 117 | export default { |
| 118 | name: 'EntriesTableSkeleton', |
| 119 | components: { |
| 120 | EntryColumnsTable, |
| 121 | }, |
| 122 | props: { |
| 123 | list: { |
| 124 | type: Array, |
| 125 | }, |
| 126 | columns: { |
| 127 | type: Object, |
| 128 | }, |
| 129 | loading: { |
| 130 | type: Boolean, |
| 131 | default: false, |
| 132 | }, |
| 133 | emptyMessage: { |
| 134 | type: String, |
| 135 | default: '', |
| 136 | }, |
| 137 | footerHeading: { |
| 138 | type: Boolean, |
| 139 | default: true, |
| 140 | }, |
| 141 | }, |
| 142 | data() { |
| 143 | return { |
| 144 | columnsIDs: [], |
| 145 | }; |
| 146 | }, |
| 147 | mixins: [ GetColumnComponent, ScopePropMixin ], |
| 148 | created() { |
| 149 | this.columnsIDs = Object.keys( this.columns ); |
| 150 | }, |
| 151 | computed: { |
| 152 | rootClasses() { |
| 153 | return { |
| 154 | 'cx-vui-panel': true, |
| 155 | 'cx-vui-panel--loading': this.loading, |
| 156 | 'cx-vui-panel-table-wrapper': true, |
| 157 | }; |
| 158 | }, |
| 159 | filteredColumns() { |
| 160 | return this.columnsIDs.filter( this.isShown ).sort( ( prev, next ) => { |
| 161 | return ( |
| 162 | ( |
| 163 | this.columns[ prev ].table_order ?? 999 |
| 164 | ) - ( |
| 165 | this.columns[ next ].table_order ?? 999 |
| 166 | ) |
| 167 | ); |
| 168 | } ); |
| 169 | }, |
| 170 | ...mapGetters( [ |
| 171 | 'isDoing', |
| 172 | ] ), |
| 173 | }, |
| 174 | methods: { |
| 175 | ...mapMutations( [ |
| 176 | 'toggleDoingAction', |
| 177 | ] ), |
| 178 | getHeadingComponent( column ) { |
| 179 | return this.getColumnComponentByPrefix( column, 'head' ); |
| 180 | }, |
| 181 | getActionHref( action ) { |
| 182 | return action?.href || 'javascript:void(0)'; |
| 183 | }, |
| 184 | getActionClass( action ) { |
| 185 | const { type = 'default', class_name = '' } = action; |
| 186 | |
| 187 | return { |
| 188 | 'list-table-item-actions-single': true, |
| 189 | [ class_name ]: true, |
| 190 | [ 'list-table-item-actions-single--type-' + type ]: true, |
| 191 | 'disabled': this.isDoing, |
| 192 | }; |
| 193 | }, |
| 194 | isShown( column ) { |
| 195 | return this.columns[ column ].show_in_table ?? true; |
| 196 | }, |
| 197 | classEntry( entryID, entry ) { |
| 198 | return { |
| 199 | 'list-table-item': true, |
| 200 | 'list-table-item--has-choose': entry?.choose?.value, |
| 201 | 'list-table-item--has-actions': entry?.actions?.value?.length, |
| 202 | ...( |
| 203 | entry?.classes?.value ?? {} |
| 204 | ), |
| 205 | }; |
| 206 | }, |
| 207 | columnType( entry, column ) { |
| 208 | return entry[ column ]?.type ?? 'string'; |
| 209 | }, |
| 210 | onClickAction( action, record, event ) { |
| 211 | if ( action?.href && '#' !== action.href ) { |
| 212 | return; |
| 213 | } |
| 214 | event.preventDefault(); |
| 215 | |
| 216 | this.commit( |
| 217 | 'setProcess', |
| 218 | { |
| 219 | action: action.value, |
| 220 | context: CLICK_ACTION, |
| 221 | payload: [ |
| 222 | [ getPrimaryId( record ) ], |
| 223 | CLICK_ACTION, |
| 224 | action?.payload, |
| 225 | record, |
| 226 | ], |
| 227 | }, |
| 228 | ); |
| 229 | |
| 230 | try { |
| 231 | this.dispatch( 'beforeRowAction' ); |
| 232 | } |
| 233 | catch ( error ) { |
| 234 | return; |
| 235 | } |
| 236 | |
| 237 | this.dispatch( 'runRowAction' ); |
| 238 | }, |
| 239 | }, |
| 240 | }; |
| 241 | </script> |
| 242 | |
| 243 | <style lang="scss"> |
| 244 | |
| 245 | .cx-vui-panel { |
| 246 | &--loading { |
| 247 | opacity: 0.5; |
| 248 | } |
| 249 | |
| 250 | &-table-wrapper { |
| 251 | margin-bottom: unset; |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | .cx-vue-list-table { |
| 256 | .list-table-heading, .list-table-item-columns { |
| 257 | justify-content: space-between; |
| 258 | } |
| 259 | |
| 260 | .list-table-item { |
| 261 | flex-direction: column; |
| 262 | position: relative; |
| 263 | background-color: #ffffff; |
| 264 | |
| 265 | &:not(:last-child) { |
| 266 | border-bottom: 1px solid #ececec; |
| 267 | } |
| 268 | |
| 269 | &:hover { |
| 270 | background-color: #e3f6fd; |
| 271 | } |
| 272 | |
| 273 | &:hover .list-table-item-actions { |
| 274 | visibility: visible; |
| 275 | } |
| 276 | |
| 277 | &--has-choose { |
| 278 | .list-table-item-actions { |
| 279 | left: 5.2em; |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | &--has-actions { |
| 284 | .list-table-item__cell.cell--choose { |
| 285 | /*transform: translateY(25%);*/ |
| 286 | } |
| 287 | |
| 288 | .list-table-item-columns { |
| 289 | margin-bottom: 1.5em; |
| 290 | } |
| 291 | } |
| 292 | |
| 293 | &-actions { |
| 294 | display: flex; |
| 295 | width: 85%; |
| 296 | column-gap: 0.5em; |
| 297 | visibility: hidden; |
| 298 | position: absolute; |
| 299 | bottom: 0.5em; |
| 300 | left: 1.5em; |
| 301 | |
| 302 | & > *:not(:last-child)::after { |
| 303 | content: '|'; |
| 304 | } |
| 305 | |
| 306 | &-single { |
| 307 | text-decoration: unset; |
| 308 | |
| 309 | &--type { |
| 310 | &-danger { |
| 311 | color: firebrick; |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | &.disabled { |
| 316 | pointer-events: none; |
| 317 | cursor: default; |
| 318 | } |
| 319 | } |
| 320 | } |
| 321 | |
| 322 | &-columns { |
| 323 | display: flex; |
| 324 | justify-content: space-between; |
| 325 | width: 100%; |
| 326 | } |
| 327 | |
| 328 | &__cell { |
| 329 | white-space: nowrap; |
| 330 | overflow: hidden; |
| 331 | position: relative; |
| 332 | padding: 8px 20px 6px; |
| 333 | |
| 334 | &:not(.cell--choose) { |
| 335 | flex: 1; |
| 336 | } |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | .list-table-heading__cell:not(.cell--choose) { |
| 341 | flex: 1 |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | body.rtl .cx-vue-list-table { |
| 346 | .list-table-item { |
| 347 | &--has-choose { |
| 348 | .list-table-item-actions { |
| 349 | right: 5.2em; |
| 350 | } |
| 351 | } |
| 352 | |
| 353 | &-actions { |
| 354 | right: 1.5em; |
| 355 | } |
| 356 | } |
| 357 | } |
| 358 | |
| 359 | |
| 360 | </style> |