135135 </NcActionButton >
136136 </template >
137137 <ul >
138- <NavigationViewItem v-for =" view in getViews " :key =" ' view' + view .id " :view =" view "
139- :show-share-sender =" false " />
138+ <NavigationViewItem v-for =" (view , index ) in orderedViews " :key =" ' view' + view .id " :view =" view "
139+ :show-share-sender =" false "
140+ :draggable =" canReorderViews "
141+ :class =" { ' view-drop-target' : dragOverIndex === index } "
142+ @dragstart .native =" onViewDragStart (index )"
143+ @dragover .native .prevent =" onViewDragOver (index )"
144+ @drop .native .prevent =" onViewDrop "
145+ @dragend .native =" onViewDragEnd " />
140146 </ul >
141147 </NcAppNavigationItem >
142148</template >
@@ -206,6 +212,9 @@ export default {
206212 data () {
207213 return {
208214 isParentOfActiveView: false ,
215+ orderedViews: [],
216+ draggedIndex: null ,
217+ dragOverIndex: null ,
209218 }
210219 },
211220
@@ -218,13 +227,28 @@ export default {
218227 return getCurrentUser ().uid
219228 },
220229 getViews () {
221- return this .views .filter (v => v .tableId === this .table .id && v .title .toLowerCase ().includes (this .filterString .toLowerCase ()))
230+ return this .views
231+ .filter (v => v .tableId === this .table .id && v .title .toLowerCase ().includes (this .filterString .toLowerCase ()))
232+ .sort ((a , b ) => {
233+ const orderA = a .sidebarOrder ?? Number .MAX_SAFE_INTEGER
234+ const orderB = b .sidebarOrder ?? Number .MAX_SAFE_INTEGER
235+ return orderA - orderB || a .id - b .id
236+ })
222237 },
223238 hasViews () {
224239 return this .getViews .length > 0
225240 },
241+ canReorderViews () {
242+ return this .canManageElement (this .table ) && ! this .filterString && this .orderedViews .length > 1
243+ },
226244 },
227245 watch: {
246+ getViews: {
247+ handler (views ) {
248+ this .orderedViews = [... views]
249+ },
250+ immediate: true ,
251+ },
228252 activeView: {
229253 immediate: true ,
230254 handler () {
@@ -240,8 +264,47 @@ export default {
240264 },
241265 },
242266 methods: {
243- ... mapActions (useTablesStore, [' favoriteTable' , ' removeFavoriteTable' , ' updateTable' ]),
267+ ... mapActions (useTablesStore, [' favoriteTable' , ' removeFavoriteTable' , ' updateTable' , ' updateView ' ]),
244268 emit,
269+ onViewDragStart (index ) {
270+ if (! this .canReorderViews ) {
271+ return
272+ }
273+ this .draggedIndex = index
274+ },
275+ onViewDragOver (index ) {
276+ if (this .draggedIndex === null || this .draggedIndex === index) {
277+ return
278+ }
279+ const moved = this .orderedViews .splice (this .draggedIndex , 1 )[0 ]
280+ this .orderedViews .splice (index, 0 , moved)
281+ this .draggedIndex = index
282+ this .dragOverIndex = index
283+ },
284+ onViewDrop () {
285+ this .persistViewOrder ()
286+ },
287+ onViewDragEnd () {
288+ this .persistViewOrder ()
289+ },
290+ async persistViewOrder () {
291+ if (this .draggedIndex === null ) {
292+ this .dragOverIndex = null
293+ return
294+ }
295+ this .draggedIndex = null
296+ this .dragOverIndex = null
297+
298+ const updates = []
299+ this .orderedViews .forEach ((view , index ) => {
300+ if (view .sidebarOrder !== index) {
301+ updates .push (this .updateView ({ id: view .id , data: { data: { sidebarOrder: index } } }))
302+ }
303+ })
304+ if (updates .length ) {
305+ await Promise .all (updates)
306+ }
307+ },
245308 deleteTable () {
246309 emit (' tables:table:delete' , this .table )
247310 },
@@ -348,4 +411,8 @@ export default {
348411 display: inline;
349412 }
350413}
414+
415+ .view - drop- target {
416+ border- top: 2px solid var (-- color- primary- element);
417+ }
351418< / style>
0 commit comments