128128 </NcActionButton >
129129 </template >
130130 <ul >
131- <NavigationViewItem v-for =" view in getViews " :key =" ' view' + view .id " :view =" view "
132- :show-share-sender =" false " />
131+ <NavigationViewItem v-for =" (view , index ) in orderedViews " :key =" ' view' + view .id " :view =" view "
132+ :show-share-sender =" false "
133+ :draggable =" canReorderViews "
134+ :class =" { ' view-drop-target' : dragOverIndex === index } "
135+ @dragstart .native =" onViewDragStart (index )"
136+ @dragover .native .prevent =" onViewDragOver (index )"
137+ @drop .native .prevent =" onViewDrop "
138+ @dragend .native =" onViewDragEnd " />
133139 </ul >
134140 </NcAppNavigationItem >
135141</template >
@@ -207,6 +213,9 @@ export default {
207213 data () {
208214 return {
209215 isParentOfActiveView: false ,
216+ orderedViews: [],
217+ draggedIndex: null ,
218+ dragOverIndex: null ,
210219 }
211220 },
212221
@@ -219,13 +228,28 @@ export default {
219228 return getCurrentUser ().uid
220229 },
221230 getViews () {
222- return this .views .filter (v => v .tableId === this .table .id && v .title .toLowerCase ().includes (this .filterString .toLowerCase ()))
231+ return this .views
232+ .filter (v => v .tableId === this .table .id && v .title .toLowerCase ().includes (this .filterString .toLowerCase ()))
233+ .sort ((a , b ) => {
234+ const orderA = a .sidebarOrder ?? Number .MAX_SAFE_INTEGER
235+ const orderB = b .sidebarOrder ?? Number .MAX_SAFE_INTEGER
236+ return orderA - orderB || a .id - b .id
237+ })
223238 },
224239 hasViews () {
225240 return this .getViews .length > 0
226241 },
242+ canReorderViews () {
243+ return this .canManageElement (this .table ) && ! this .filterString && this .orderedViews .length > 1
244+ },
227245 },
228246 watch: {
247+ getViews: {
248+ handler (views ) {
249+ this .orderedViews = [... views]
250+ },
251+ immediate: true ,
252+ },
229253 activeView () {
230254 if (! this .isParentOfActiveView && this .activeView ? .tableId === this .table ? .id ) {
231255 this .isParentOfActiveView = true
@@ -238,8 +262,47 @@ export default {
238262 },
239263 },
240264 methods: {
241- ... mapActions (useTablesStore, [' favoriteTable' , ' removeFavoriteTable' , ' updateTable' ]),
265+ ... mapActions (useTablesStore, [' favoriteTable' , ' removeFavoriteTable' , ' updateTable' , ' updateView ' ]),
242266 emit,
267+ onViewDragStart (index ) {
268+ if (! this .canReorderViews ) {
269+ return
270+ }
271+ this .draggedIndex = index
272+ },
273+ onViewDragOver (index ) {
274+ if (this .draggedIndex === null || this .draggedIndex === index) {
275+ return
276+ }
277+ const moved = this .orderedViews .splice (this .draggedIndex , 1 )[0 ]
278+ this .orderedViews .splice (index, 0 , moved)
279+ this .draggedIndex = index
280+ this .dragOverIndex = index
281+ },
282+ onViewDrop () {
283+ this .persistViewOrder ()
284+ },
285+ onViewDragEnd () {
286+ this .persistViewOrder ()
287+ },
288+ async persistViewOrder () {
289+ if (this .draggedIndex === null ) {
290+ this .dragOverIndex = null
291+ return
292+ }
293+ this .draggedIndex = null
294+ this .dragOverIndex = null
295+
296+ const updates = []
297+ this .orderedViews .forEach ((view , index ) => {
298+ if (view .sidebarOrder !== index) {
299+ updates .push (this .updateView ({ id: view .id , data: { data: { sidebarOrder: index } } }))
300+ }
301+ })
302+ if (updates .length ) {
303+ await Promise .all (updates)
304+ }
305+ },
243306 deleteTable () {
244307 emit (' tables:table:delete' , this .table )
245308 },
@@ -343,4 +406,8 @@ export default {
343406 display: inline;
344407 }
345408}
409+
410+ .view - drop- target {
411+ border- top: 2px solid var (-- color- primary- element);
412+ }
346413< / style>
0 commit comments