Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion web-app/packages/admin-app/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial
</router-view>
<router-view v-slot="{ Component }">
<instance-maintenance-message v-if="pingData && pingData.maintenance" />
<CheckForUpdates />
<transition name="fade">
<component :is="Component" />
</transition>
Expand All @@ -42,6 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial
</template>

<script lang="ts">
import { CheckForUpdates } from '@mergin/admin-lib'
import {
InstanceMaintenanceMessage,
DialogWindows,
Expand All @@ -65,7 +67,8 @@ export default defineComponent({
components: {
Notifications,
DialogWindows,
InstanceMaintenanceMessage
InstanceMaintenanceMessage,
CheckForUpdates
},
metaInfo() {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ const sidebarItems = computed<SideBarItemModel[]>(() => [
</script>

<template>
<side-bar-template :sidebarItems="sidebarItems" />
<side-bar-template :sidebarItems="sidebarItems">
<template #subtitle>Administration</template>
</side-bar-template>
</template>

<style lang="scss" scoped></style>
142 changes: 52 additions & 90 deletions web-app/packages/admin-app/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ import {
SettingsView,
ProjectsView,
ProjectView,
AdminRoutes
AdminRoutes,
ProjectFilesView,
ProjectSettingsView,
ProjectVersionView,
ProjectVersionsView
} from '@mergin/admin-lib'
import {
NotFoundView,
routeUtils,
// errorUtils,
// FileBrowserView,
// ProjectVersionsView,
// FileVersionDetailView,
FileVersionDetailView,
useUserStore
} from '@mergin/lib'
import { Pinia } from 'pinia'
Expand Down Expand Up @@ -79,98 +80,60 @@ export const createRouter = (pinia: Pinia) => {
},
props: true
},
{
path: '/projects/:namespace/:projectName/history/:version_id',
components: {
default: ProjectVersionView,
sidebar: Sidebar,
header: AppHeader
},
props: true
},
{
path: '/projects/:namespace/:projectName/history/:version_id/:path',
name: 'file-version-detail',
components: {
default: FileVersionDetailView,
sidebar: Sidebar,
header: AppHeader
},
props: true
},
{
path: '/projects/:namespace/:projectName?',
name: AdminRoutes.PROJECT,
components: {
default: ProjectView,
sidebar: Sidebar,
header: AppHeader
},
props: true
props: true,
children: [
{
path: '',
name: AdminRoutes.PROJECT,
component: ProjectFilesView,
props: true
},
{
path: 'tree/:location?',
name: 'project-tree',
component: ProjectFilesView,
props: true
},
{
path: 'settings',
name: 'project-settings',
component: ProjectSettingsView,
props: true
},
{
path: 'history',
name: 'project-versions',
component: ProjectVersionsView,
props: true
}
]
},

// redirect: { name: 'project-tree' },
// children: [
// {
// path: 'blob/:location*',
// name: 'blob',
// component: NotFoundView,
// props(route) {
// return {
// asAdmin: true,
// namespace: route.params.namespace,
// projectName: route.params.projectName,
// location: route.params.location
// }
// }
// },
// {
// path: 'tree/:location*',
// name: 'project-tree',
// component: FileBrowserView,
// props(route) {
// return {
// asAdmin: true,
// namespace: route.params.namespace,
// projectName: route.params.projectName,
// location: route.params.location
// }
// }
// },
// {
// path: 'settings',
// name: 'project-settings',
// component: ProjectSettingsView,
// props(route) {
// return {
// asAdmin: true,
// namespace: route.params.namespace,
// projectName: route.params.projectName
// }
// }
// },
// {
// path: 'history',
// name: 'project-versions',
// component: ProjectVersionsView,
// props(route) {
// return {
// asAdmin: true,
// namespace: route.params.namespace,
// projectName: route.params.projectName
// }
// }
// },
// {
// path: 'history/:version_id',
// name: 'project-versions-detail',
// component: NotFoundView,
// props(route) {
// return {
// asAdmin: true,
// namespace: route.params.namespace,
// projectName: route.params.projectName,
// version_id: route.params.version_id
// }
// }
// },
// {
// path: 'history/:version_id/:path',
// name: 'file-version-detail',
// component: FileVersionDetailView,
// props(route) {
// return {
// asAdmin: true,
// namespace: route.params.namespace,
// projectName: route.params.projectName,
// version_id: route.params.version_id,
// path: route.params.path
// }
// }
// }
// ]
// },
{
path: '/settings',
name: AdminRoutes.SETTINGS,
Expand All @@ -187,7 +150,6 @@ export const createRouter = (pinia: Pinia) => {
/** Handles redirect to /login when user is not authenticated. */
router.beforeEach((to, from, next) => {
const userStore = useUserStore(pinia)
routeUtils.isAuthenticatedGuard(to, from, next, userStore)
routeUtils.isSuperUser(to, from, next, userStore)
})

Expand Down
2 changes: 2 additions & 0 deletions web-app/packages/admin-lib/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ declare module 'vue' {
PInputSwitch: typeof import('primevue/inputswitch')['default']
PInputText: typeof import('primevue/inputtext')['default']
PPassword: typeof import('primevue/password')['default']
PTabPanel: typeof import('primevue/tabpanel')['default']
PTabView: typeof import('primevue/tabview')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial
<template>
<article>
<server-not-configured />
<check-for-updates />
<slot />
</article>
</template>

<script lang="ts" setup>
/** Consider if we want to support this */
import CheckForUpdates from './CheckForUpdates.vue'
import ServerNotConfigured from './ServerNotConfigured.vue'
</script>
<style lang="scss" scoped></style>
5 changes: 4 additions & 1 deletion web-app/packages/admin-lib/src/modules/admin/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ export enum AdminRoutes {
ACCOUNT = 'account',
PROJECTS = 'projects',
PROJECT = 'project',
SETTINGS = 'settings'
SETTINGS = 'settings',
ProjectTree = 'project-tree',
ProjectHistory = 'project-versions',
ProjectSettings = 'project-settings'
}

export const getRoutes = (): RouteRecord[] => []
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<template>
<div>
<!-- Searching -->
<app-container
v-if="searchFilter !== '' || Object.keys(project?.files ?? {}).length > 0"
>
<app-section ground>
<div class="flex align-items-center">
<span class="p-input-icon-left flex-grow-1">
<i class="ti ti-search paragraph-p3"></i>
<PInputText
placeholder="Search files"
data-cy="search-files-field"
v-model="searchFilter"
class="w-full"
/>
</span>
<AppMenu :items="filterMenuItems" />
</div>
</app-section>
</app-container>

<app-container v-if="projectName">
<app-section>
<files-table
:project-name="projectName"
:namespace="namespace"
:location="location"
:options="options"
:search="searchFilter"
@row-click="rowClick"
/>
</app-section>
</app-container>
</div>
</template>

<script setup lang="ts">
import {
AppSection,
AppContainer,
AppMenu,
useProjectStore,
FilesTable,
ProjectApi
} from '@mergin/lib'
import { storeToRefs } from 'pinia'
import { MenuItem, MenuItemCommandEvent } from 'primevue/menuitem'
import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'

interface Props {
namespace?: string
projectName?: string
location?: string
}

const props = withDefaults(defineProps<Props>(), {
location: ''
})

const router = useRouter()
const projectStore = useProjectStore()
const { project } = storeToRefs(projectStore)

const options = ref({
sortBy: 'name',
sortDesc: 1
})
const searchFilter = ref('')

const filterMenuItems = computed<MenuItem[]>(() => {
const items = [
{ label: 'Sort by name A-Z', key: 'name', sortDesc: 1 },
{ label: 'Sort by name Z-A', key: 'name', sortDesc: -1 },
{ label: 'Sort by last modified', key: 'mtime', sortDesc: -1 },
{ label: 'Sort by file size', key: 'size', sortDesc: -1 }
]

return items.map((item) => ({
...item,
command: (e: MenuItemCommandEvent) => menuItemClick(e),
class:
options.value.sortBy === item.key &&
options.value.sortDesc === item.sortDesc
? 'bg-primary-400'
: ''
}))
})

const rowClick = (file: {
// TODO: use proper interface with all attributes coming from files table
path: string
type: 'folder' | 'file'
link: string
}) => {
if (file.type === 'folder') {
router.push({ path: file.link })
return
}
// added random number to request avoid to browser caching files
const url = ProjectApi.constructDownloadProjectFileUrl(
props.namespace,
props.projectName,
encodeURIComponent(file?.path)
)
window.location.href = url
}

const menuItemClick = (e: MenuItemCommandEvent) => {
options.value.sortBy = String(e.item.key)
options.value.sortDesc = e.item.sortDesc
}
</script>

<style lang="scss" scoped></style>
Loading