mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-08 00:02:15 +01:00
add billing, organization settings and import to navigation
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head, usePage } from '@inertiajs/vue3';
|
||||||
import Banner from '@/Components/Banner.vue';
|
import Banner from '@/Components/Banner.vue';
|
||||||
import OrganizationSwitcher from '@/Components/OrganizationSwitcher.vue';
|
import OrganizationSwitcher from '@/Components/OrganizationSwitcher.vue';
|
||||||
import CurrentSidebarTimer from '@/Components/CurrentSidebarTimer.vue';
|
import CurrentSidebarTimer from '@/Components/CurrentSidebarTimer.vue';
|
||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
UserGroupIcon,
|
UserGroupIcon,
|
||||||
Bars3Icon,
|
Bars3Icon,
|
||||||
XMarkIcon,
|
XMarkIcon,
|
||||||
|
CreditCardIcon,
|
||||||
} from '@heroicons/vue/20/solid';
|
} from '@heroicons/vue/20/solid';
|
||||||
import NavigationSidebarItem from '@/Components/NavigationSidebarItem.vue';
|
import NavigationSidebarItem from '@/Components/NavigationSidebarItem.vue';
|
||||||
import UserSettingsIcon from '@/Components/UserSettingsIcon.vue';
|
import UserSettingsIcon from '@/Components/UserSettingsIcon.vue';
|
||||||
@@ -22,11 +23,15 @@ import { onMounted, ref } from 'vue';
|
|||||||
import NotificationContainer from '@/Components/NotificationContainer.vue';
|
import NotificationContainer from '@/Components/NotificationContainer.vue';
|
||||||
import { initializeStores } from '@/utils/init';
|
import { initializeStores } from '@/utils/init';
|
||||||
import {
|
import {
|
||||||
|
canUpdateOrganization,
|
||||||
canViewClients,
|
canViewClients,
|
||||||
canViewMembers,
|
canViewMembers,
|
||||||
canViewProjects,
|
canViewProjects,
|
||||||
canViewTags,
|
canViewTags,
|
||||||
} from '@/utils/permissions';
|
} from '@/utils/permissions';
|
||||||
|
import { isBillingActivated } from '@/utils/billing';
|
||||||
|
import type { User } from '@/types/models';
|
||||||
|
import { ArrowsRightLeftIcon } from '@heroicons/vue/16/solid';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
title: String,
|
title: String,
|
||||||
@@ -41,6 +46,12 @@ onMounted(async () => {
|
|||||||
initializeStores();
|
initializeStores();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const page = usePage<{
|
||||||
|
auth: {
|
||||||
|
user: User;
|
||||||
|
};
|
||||||
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -64,7 +75,7 @@ onMounted(async () => {
|
|||||||
<CurrentSidebarTimer></CurrentSidebarTimer>
|
<CurrentSidebarTimer></CurrentSidebarTimer>
|
||||||
</div>
|
</div>
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="space-y-1">
|
<ul>
|
||||||
<NavigationSidebarItem
|
<NavigationSidebarItem
|
||||||
title="Dashboard"
|
title="Dashboard"
|
||||||
:icon="HomeIcon"
|
:icon="HomeIcon"
|
||||||
@@ -85,10 +96,13 @@ onMounted(async () => {
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="text-muted text-sm font-bold pt-6 pb-4">Manage</div>
|
<div
|
||||||
|
class="text-text-tertiary text-sm font-semibold pt-5 pb-1.5">
|
||||||
|
Manage
|
||||||
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="space-y-1">
|
<ul>
|
||||||
<NavigationSidebarItem
|
<NavigationSidebarItem
|
||||||
v-if="canViewProjects()"
|
v-if="canViewProjects()"
|
||||||
title="Projects"
|
title="Projects"
|
||||||
@@ -117,13 +131,51 @@ onMounted(async () => {
|
|||||||
:href="route('tags')"></NavigationSidebarItem>
|
:href="route('tags')"></NavigationSidebarItem>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
<div
|
||||||
|
class="text-text-tertiary text-sm font-semibold pt-5 pb-1.5">
|
||||||
|
Admin
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<NavigationSidebarItem
|
||||||
|
v-if="
|
||||||
|
canUpdateOrganization() && isBillingActivated()
|
||||||
|
"
|
||||||
|
title="Billing"
|
||||||
|
:icon="CreditCardIcon"
|
||||||
|
href="/billing"></NavigationSidebarItem>
|
||||||
|
<NavigationSidebarItem
|
||||||
|
v-if="canUpdateOrganization()"
|
||||||
|
title="Import"
|
||||||
|
:icon="ArrowsRightLeftIcon"
|
||||||
|
:current="route().current('import')"
|
||||||
|
:href="route('import')"></NavigationSidebarItem>
|
||||||
|
<NavigationSidebarItem
|
||||||
|
v-if="canUpdateOrganization()"
|
||||||
|
title="Settings"
|
||||||
|
:icon="Cog6ToothIcon"
|
||||||
|
:href="
|
||||||
|
route(
|
||||||
|
'teams.show',
|
||||||
|
page.props.auth.user.current_team.id
|
||||||
|
)
|
||||||
|
"
|
||||||
|
:current="
|
||||||
|
route().current(
|
||||||
|
'teams.show',
|
||||||
|
page.props.auth.user.current_team.id
|
||||||
|
)
|
||||||
|
"></NavigationSidebarItem>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul
|
<ul
|
||||||
class="border-t border-default-background-separator pt-3 flex justify-between pr-4 items-center">
|
class="border-t border-default-background-separator pt-3 flex justify-between pr-4 items-center">
|
||||||
<NavigationSidebarItem
|
<NavigationSidebarItem
|
||||||
class="flex-1"
|
class="flex-1"
|
||||||
title="Settings"
|
title="Profile Settings"
|
||||||
:icon="Cog6ToothIcon"
|
:icon="Cog6ToothIcon"
|
||||||
:href="route('profile.show')"></NavigationSidebarItem>
|
:href="route('profile.show')"></NavigationSidebarItem>
|
||||||
|
|
||||||
|
|||||||
32
resources/js/Pages/Import.vue
Normal file
32
resources/js/Pages/Import.vue
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import MainContainer from '@/Pages/MainContainer.vue';
|
||||||
|
import AppLayout from '@/Layouts/AppLayout.vue';
|
||||||
|
import { PlusIcon, ArrowsRightLeftIcon } from '@heroicons/vue/16/solid';
|
||||||
|
import SecondaryButton from '@/Components/SecondaryButton.vue';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import PageTitle from '@/Components/Common/PageTitle.vue';
|
||||||
|
import { canCreateTags } from '@/utils/permissions';
|
||||||
|
import ImportData from '@/Pages/Teams/Partials/ImportData.vue';
|
||||||
|
const createTag = ref(false);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AppLayout title="Import" data-testid="import_view">
|
||||||
|
<MainContainer
|
||||||
|
class="py-5 border-b border-default-background-separator flex justify-between items-center">
|
||||||
|
<div class="flex items-center space-x-6">
|
||||||
|
<PageTitle :icon="ArrowsRightLeftIcon" title="Import">
|
||||||
|
</PageTitle>
|
||||||
|
</div>
|
||||||
|
<SecondaryButton
|
||||||
|
v-if="canCreateTags()"
|
||||||
|
:icon="PlusIcon"
|
||||||
|
@click="createTag = true"
|
||||||
|
>Create Tag</SecondaryButton
|
||||||
|
>
|
||||||
|
</MainContainer>
|
||||||
|
<MainContainer class="py-6">
|
||||||
|
<ImportData></ImportData>
|
||||||
|
</MainContainer>
|
||||||
|
</AppLayout>
|
||||||
|
</template>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import FormSection from '@/Components/FormSection.vue';
|
import FormSection from '@/Components/FormSection.vue';
|
||||||
import PrimaryButton from '@/Components/PrimaryButton.vue';
|
import PrimaryButton from '@/Components/PrimaryButton.vue';
|
||||||
import type { Organization } from '@/types/models';
|
|
||||||
import { computed, onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
import { useNotificationsStore } from '@/utils/notification';
|
import { useNotificationsStore } from '@/utils/notification';
|
||||||
import { api } from '../../../../../openapi.json.client';
|
import { api } from '../../../../../openapi.json.client';
|
||||||
@@ -11,11 +10,6 @@ import { getCurrentOrganizationId } from '@/utils/useUser';
|
|||||||
import type { ImportReport, ImportType } from '@/utils/api';
|
import type { ImportReport, ImportType } from '@/utils/api';
|
||||||
import DialogModal from '@/Components/DialogModal.vue';
|
import DialogModal from '@/Components/DialogModal.vue';
|
||||||
import SecondaryButton from '@/Components/SecondaryButton.vue';
|
import SecondaryButton from '@/Components/SecondaryButton.vue';
|
||||||
|
|
||||||
defineProps<{
|
|
||||||
team: Organization;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const importTypeOptions = ref<ImportType[]>([]);
|
const importTypeOptions = ref<ImportType[]>([]);
|
||||||
|
|
||||||
const { addNotification } = useNotificationsStore();
|
const { addNotification } = useNotificationsStore();
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ Route::middleware([
|
|||||||
return Inertia::render('Tags');
|
return Inertia::render('Tags');
|
||||||
})->name('tags');
|
})->name('tags');
|
||||||
|
|
||||||
|
Route::get('/import', function () {
|
||||||
|
return Inertia::render('Import');
|
||||||
|
})->name('import');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('health-check/up', [HealthCheckController::class, 'up']);
|
Route::get('health-check/up', [HealthCheckController::class, 'up']);
|
||||||
|
|||||||
Reference in New Issue
Block a user