mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-12 02:02:15 +01:00
add linter, prettier and typescript support for jetstream (#1)
* add linter, prettier and typescript support for jetstream * add github actions for lint, build and typecheck * add composer install to build action * fix composer lock * add ext-intl and fixed php version * fix intl php extension install * add tip php extension to github npm build action * fix php version to 8.3.1 * change github php base action * fix primary button default type * updated typescript types from Team to Organization --------- Co-authored-by: Gregor Vostrak <gregorvostrak@Gregors-MacBook-Pro.local>
This commit is contained in:
@@ -1,18 +1,20 @@
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import ApiTokenManager from '@/Pages/API/Partials/ApiTokenManager.vue';
|
||||
import AppLayout from '@/Layouts/AppLayout.vue';
|
||||
import type { Token } from '@/types/jetstream';
|
||||
|
||||
defineProps({
|
||||
tokens: Array,
|
||||
availablePermissions: Array,
|
||||
defaultPermissions: Array,
|
||||
});
|
||||
defineProps<{
|
||||
tokens: Token[];
|
||||
availablePermissions: string[];
|
||||
defaultPermissions: string[];
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout title="API Tokens">
|
||||
<template #header>
|
||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||
<h2
|
||||
class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||
API Tokens
|
||||
</h2>
|
||||
</template>
|
||||
@@ -22,8 +24,7 @@ defineProps({
|
||||
<ApiTokenManager
|
||||
:tokens="tokens"
|
||||
:available-permissions="availablePermissions"
|
||||
:default-permissions="defaultPermissions"
|
||||
/>
|
||||
:default-permissions="defaultPermissions" />
|
||||
</div>
|
||||
</div>
|
||||
</AppLayout>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useForm } from '@inertiajs/vue3';
|
||||
import { useForm, usePage } from '@inertiajs/vue3';
|
||||
import ActionMessage from '@/Components/ActionMessage.vue';
|
||||
import ActionSection from '@/Components/ActionSection.vue';
|
||||
import Checkbox from '@/Components/Checkbox.vue';
|
||||
@@ -14,27 +14,38 @@ import PrimaryButton from '@/Components/PrimaryButton.vue';
|
||||
import SecondaryButton from '@/Components/SecondaryButton.vue';
|
||||
import SectionBorder from '@/Components/SectionBorder.vue';
|
||||
import TextInput from '@/Components/TextInput.vue';
|
||||
import type { Token } from '@/types/jetstream';
|
||||
|
||||
const props = defineProps({
|
||||
tokens: Array,
|
||||
availablePermissions: Array,
|
||||
defaultPermissions: Array,
|
||||
});
|
||||
const props = defineProps<{
|
||||
tokens: Token[];
|
||||
availablePermissions: string[];
|
||||
defaultPermissions: string[];
|
||||
}>();
|
||||
|
||||
const createApiTokenForm = useForm({
|
||||
name: '',
|
||||
permissions: props.defaultPermissions,
|
||||
});
|
||||
|
||||
const updateApiTokenForm = useForm({
|
||||
const page = usePage<{
|
||||
jetstream: {
|
||||
flash: {
|
||||
token: string;
|
||||
};
|
||||
};
|
||||
}>();
|
||||
|
||||
const updateApiTokenForm = useForm<{
|
||||
permissions: string[];
|
||||
}>({
|
||||
permissions: [],
|
||||
});
|
||||
|
||||
const deleteApiTokenForm = useForm({});
|
||||
|
||||
const displayingToken = ref(false);
|
||||
const managingPermissionsFor = ref(null);
|
||||
const apiTokenBeingDeleted = ref(null);
|
||||
const managingPermissionsFor = ref<Token | null>(null);
|
||||
const apiTokenBeingDeleted = ref<Token | null>(null);
|
||||
|
||||
const createApiToken = () => {
|
||||
createApiTokenForm.post(route('api-tokens.store'), {
|
||||
@@ -46,29 +57,35 @@ const createApiToken = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const manageApiTokenPermissions = (token) => {
|
||||
const manageApiTokenPermissions = (token: Token) => {
|
||||
updateApiTokenForm.permissions = token.abilities;
|
||||
managingPermissionsFor.value = token;
|
||||
};
|
||||
|
||||
const updateApiToken = () => {
|
||||
updateApiTokenForm.put(route('api-tokens.update', managingPermissionsFor.value), {
|
||||
preserveScroll: true,
|
||||
preserveState: true,
|
||||
onSuccess: () => (managingPermissionsFor.value = null),
|
||||
});
|
||||
updateApiTokenForm.put(
|
||||
route('api-tokens.update', managingPermissionsFor.value?.id),
|
||||
{
|
||||
preserveScroll: true,
|
||||
preserveState: true,
|
||||
onSuccess: () => (managingPermissionsFor.value = null),
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const confirmApiTokenDeletion = (token) => {
|
||||
const confirmApiTokenDeletion = (token: Token) => {
|
||||
apiTokenBeingDeleted.value = token;
|
||||
};
|
||||
|
||||
const deleteApiToken = () => {
|
||||
deleteApiTokenForm.delete(route('api-tokens.destroy', apiTokenBeingDeleted.value), {
|
||||
preserveScroll: true,
|
||||
preserveState: true,
|
||||
onSuccess: () => (apiTokenBeingDeleted.value = null),
|
||||
});
|
||||
deleteApiTokenForm.delete(
|
||||
route('api-tokens.destroy', apiTokenBeingDeleted.value?.id),
|
||||
{
|
||||
preserveScroll: true,
|
||||
preserveState: true,
|
||||
onSuccess: () => (apiTokenBeingDeleted.value = null),
|
||||
}
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -76,12 +93,11 @@ const deleteApiToken = () => {
|
||||
<div>
|
||||
<!-- Generate API Token -->
|
||||
<FormSection @submitted="createApiToken">
|
||||
<template #title>
|
||||
Create API Token
|
||||
</template>
|
||||
<template #title> Create API Token </template>
|
||||
|
||||
<template #description>
|
||||
API tokens allow third-party services to authenticate with our application on your behalf.
|
||||
API tokens allow third-party services to authenticate with our
|
||||
application on your behalf.
|
||||
</template>
|
||||
|
||||
<template #form>
|
||||
@@ -93,9 +109,10 @@ const deleteApiToken = () => {
|
||||
v-model="createApiTokenForm.name"
|
||||
type="text"
|
||||
class="mt-1 block w-full"
|
||||
autofocus
|
||||
/>
|
||||
<InputError :message="createApiTokenForm.errors.name" class="mt-2" />
|
||||
autofocus />
|
||||
<InputError
|
||||
:message="createApiTokenForm.errors.name"
|
||||
class="mt-2" />
|
||||
</div>
|
||||
|
||||
<!-- Token Permissions -->
|
||||
@@ -103,10 +120,19 @@ const deleteApiToken = () => {
|
||||
<InputLabel for="permissions" value="Permissions" />
|
||||
|
||||
<div class="mt-2 grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div v-for="permission in availablePermissions" :key="permission">
|
||||
<div
|
||||
v-for="permission in availablePermissions"
|
||||
:key="permission">
|
||||
<label class="flex items-center">
|
||||
<Checkbox v-model:checked="createApiTokenForm.permissions" :value="permission" />
|
||||
<span class="ms-2 text-sm text-gray-600 dark:text-gray-400">{{ permission }}</span>
|
||||
<Checkbox
|
||||
v-model:checked="
|
||||
createApiTokenForm.permissions
|
||||
"
|
||||
:value="permission" />
|
||||
<span
|
||||
class="ms-2 text-sm text-gray-600 dark:text-gray-400"
|
||||
>{{ permission }}</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -114,11 +140,15 @@ const deleteApiToken = () => {
|
||||
</template>
|
||||
|
||||
<template #actions>
|
||||
<ActionMessage :on="createApiTokenForm.recentlySuccessful" class="me-3">
|
||||
<ActionMessage
|
||||
:on="createApiTokenForm.recentlySuccessful"
|
||||
class="me-3">
|
||||
Created.
|
||||
</ActionMessage>
|
||||
|
||||
<PrimaryButton :class="{ 'opacity-25': createApiTokenForm.processing }" :disabled="createApiTokenForm.processing">
|
||||
<PrimaryButton
|
||||
:class="{ 'opacity-25': createApiTokenForm.processing }"
|
||||
:disabled="createApiTokenForm.processing">
|
||||
Create
|
||||
</PrimaryButton>
|
||||
</template>
|
||||
@@ -130,36 +160,43 @@ const deleteApiToken = () => {
|
||||
<!-- Manage API Tokens -->
|
||||
<div class="mt-10 sm:mt-0">
|
||||
<ActionSection>
|
||||
<template #title>
|
||||
Manage API Tokens
|
||||
</template>
|
||||
<template #title> Manage API Tokens </template>
|
||||
|
||||
<template #description>
|
||||
You may delete any of your existing tokens if they are no longer needed.
|
||||
You may delete any of your existing tokens if they are
|
||||
no longer needed.
|
||||
</template>
|
||||
|
||||
<!-- API Token List -->
|
||||
<template #content>
|
||||
<div class="space-y-6">
|
||||
<div v-for="token in tokens" :key="token.id" class="flex items-center justify-between">
|
||||
<div
|
||||
v-for="token in tokens"
|
||||
:key="token.id"
|
||||
class="flex items-center justify-between">
|
||||
<div class="break-all dark:text-white">
|
||||
{{ token.name }}
|
||||
</div>
|
||||
|
||||
<div class="flex items-center ms-2">
|
||||
<div v-if="token.last_used_ago" class="text-sm text-gray-400">
|
||||
<div
|
||||
v-if="token.last_used_ago"
|
||||
class="text-sm text-gray-400">
|
||||
Last used {{ token.last_used_ago }}
|
||||
</div>
|
||||
|
||||
<button
|
||||
v-if="availablePermissions.length > 0"
|
||||
class="cursor-pointer ms-6 text-sm text-gray-400 underline"
|
||||
@click="manageApiTokenPermissions(token)"
|
||||
>
|
||||
@click="
|
||||
manageApiTokenPermissions(token)
|
||||
">
|
||||
Permissions
|
||||
</button>
|
||||
|
||||
<button class="cursor-pointer ms-6 text-sm text-red-500" @click="confirmApiTokenDeletion(token)">
|
||||
<button
|
||||
class="cursor-pointer ms-6 text-sm text-red-500"
|
||||
@click="confirmApiTokenDeletion(token)">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
@@ -172,17 +209,18 @@ const deleteApiToken = () => {
|
||||
|
||||
<!-- Token Value Modal -->
|
||||
<DialogModal :show="displayingToken" @close="displayingToken = false">
|
||||
<template #title>
|
||||
API Token
|
||||
</template>
|
||||
<template #title> API Token </template>
|
||||
|
||||
<template #content>
|
||||
<div>
|
||||
Please copy your new API token. For your security, it won't be shown again.
|
||||
Please copy your new API token. For your security, it won't
|
||||
be shown again.
|
||||
</div>
|
||||
|
||||
<div v-if="$page.props.jetstream.flash.token" class="mt-4 bg-gray-100 dark:bg-gray-900 px-4 py-2 rounded font-mono text-sm text-gray-500 break-all">
|
||||
{{ $page.props.jetstream.flash.token }}
|
||||
<div
|
||||
v-if="page.props.jetstream.flash.token"
|
||||
class="mt-4 bg-gray-100 dark:bg-gray-900 px-4 py-2 rounded font-mono text-sm text-gray-500 break-all">
|
||||
{{ page.props.jetstream.flash.token }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -194,17 +232,24 @@ const deleteApiToken = () => {
|
||||
</DialogModal>
|
||||
|
||||
<!-- API Token Permissions Modal -->
|
||||
<DialogModal :show="managingPermissionsFor != null" @close="managingPermissionsFor = null">
|
||||
<template #title>
|
||||
API Token Permissions
|
||||
</template>
|
||||
<DialogModal
|
||||
:show="managingPermissionsFor != null"
|
||||
@close="managingPermissionsFor = null">
|
||||
<template #title> API Token Permissions </template>
|
||||
|
||||
<template #content>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div v-for="permission in availablePermissions" :key="permission">
|
||||
<div
|
||||
v-for="permission in availablePermissions"
|
||||
:key="permission">
|
||||
<label class="flex items-center">
|
||||
<Checkbox v-model:checked="updateApiTokenForm.permissions" :value="permission" />
|
||||
<span class="ms-2 text-sm text-gray-600 dark:text-gray-400">{{ permission }}</span>
|
||||
<Checkbox
|
||||
v-model:checked="updateApiTokenForm.permissions"
|
||||
:value="permission" />
|
||||
<span
|
||||
class="ms-2 text-sm text-gray-600 dark:text-gray-400"
|
||||
>{{ permission }}</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -219,18 +264,17 @@ const deleteApiToken = () => {
|
||||
class="ms-3"
|
||||
:class="{ 'opacity-25': updateApiTokenForm.processing }"
|
||||
:disabled="updateApiTokenForm.processing"
|
||||
@click="updateApiToken"
|
||||
>
|
||||
@click="updateApiToken">
|
||||
Save
|
||||
</PrimaryButton>
|
||||
</template>
|
||||
</DialogModal>
|
||||
|
||||
<!-- Delete Token Confirmation Modal -->
|
||||
<ConfirmationModal :show="apiTokenBeingDeleted != null" @close="apiTokenBeingDeleted = null">
|
||||
<template #title>
|
||||
Delete API Token
|
||||
</template>
|
||||
<ConfirmationModal
|
||||
:show="apiTokenBeingDeleted != null"
|
||||
@close="apiTokenBeingDeleted = null">
|
||||
<template #title> Delete API Token </template>
|
||||
|
||||
<template #content>
|
||||
Are you sure you would like to delete this API token?
|
||||
@@ -245,8 +289,7 @@ const deleteApiToken = () => {
|
||||
class="ms-3"
|
||||
:class="{ 'opacity-25': deleteApiTokenForm.processing }"
|
||||
:disabled="deleteApiTokenForm.processing"
|
||||
@click="deleteApiToken"
|
||||
>
|
||||
@click="deleteApiToken">
|
||||
Delete
|
||||
</DangerButton>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user