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:
Gregor Vostrak
2024-01-21 22:35:43 +01:00
committed by GitHub
parent 0a8d958ccc
commit 27140d4ffc
73 changed files with 4727 additions and 886 deletions

View File

@@ -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>

View File

@@ -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>