Skip to content

Commit

Permalink
feat: backport features from real-world project
Browse files Browse the repository at this point in the history
  • Loading branch information
lewebsimple committed Dec 14, 2023
1 parent a409bc8 commit fb50abe
Show file tree
Hide file tree
Showing 14 changed files with 72 additions and 35 deletions.
1 change: 1 addition & 0 deletions app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default defineAppConfig({
nuxtIcon: {},
ui: {
// Colors
primary: "indigo",
Expand Down
6 changes: 1 addition & 5 deletions app/components/app/TheAppFooter.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
<script setup lang="ts">
const { isAdministrator } = useAuth();
</script>

<template>
<footer class="py-2 bg-muted">
<div class="container flex items-center gap-4">
<AppVersion class="mr-auto" />
<UButton v-if="isAdministrator" color="gray" variant="link" to="/auth/users" label="Utilisateurs" />
<AuthUsersButton />
<AuthButton />
</div>
</footer>
Expand Down
2 changes: 1 addition & 1 deletion auth/components/auth-user/TheAuthUsers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ watch([filters, sort], onRefetch, { deep: true });
</script>

<template>
<div class="space-y-4">
<div class="space-y-8">
<div class="flex flex-wrap items-center gap-4">
<h1 class="h1">Utilisateurs</h1>
<TheAuthUsersCreate @refetch="onRefetch" />
Expand Down
17 changes: 10 additions & 7 deletions auth/components/auth-user/TheAuthUsersActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
const props = defineProps<{ selected: TheAuthUserFragment[] }>();
const emit = defineEmits<{ (event: "refetch"): void }>();
const actions = {
destroy: {
label: "Supprimer",
title: "Supprimer les utilisateurs",
icon: "i-heroicons-trash",
},
};
const actions = [
[
{
key: "destroy",
label: "Supprimer",
title: "Supprimer les utilisateurs",
icon: "i-heroicons-trash",
},
],
];
</script>

<template>
Expand Down
2 changes: 1 addition & 1 deletion auth/components/forms/FormAuthUserDestroy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { authUserDestroyMany } = useAuthUserMutations();
async function onAuthUserDestroySubmit() {
try {
const { error } = await authUserDestroyMany({ ids: props.authUsers.map(({ id }) => id) });
const { error } = await authUserDestroyMany({ authUserIds: props.authUsers.map(({ id }) => id) });
if (error) throw new Error(error.message);
return props.authUsers.length > 1 ? `${props.authUsers.length} utilisateurs supprimés` : `1 utilisateur supprimé`;
} catch (error) {
Expand Down
7 changes: 7 additions & 0 deletions auth/components/helpers/AuthUsersButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script setup lang="ts">
const { isAdministrator } = useAuth();
</script>

<template>
<UButton v-if="isAdministrator" color="gray" variant="link" to="/auth/users" label="Utilisateurs" />
</template>
4 changes: 2 additions & 2 deletions auth/composables/auth-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ export function useAuthUserMutations() {
// Destroy many AuthUsers
const { executeMutation: authUserDestroyMany } = useMutation(
graphql(`
mutation AuthUserDestroyMany($ids: [String!]!) {
authUserDestroyMany(authUserIds: $ids)
mutation AuthUserDestroyMany($authUserIds: [String!]!) {
authUserDestroyMany(authUserIds: $authUserIds)
}
`),
);
Expand Down
4 changes: 2 additions & 2 deletions graphql/utils/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const documents = {
"\n fragment TheAuthUser on AuthUser {\n id\n email\n role\n }\n": types.TheAuthUserFragmentDoc,
"\n query TheAuthUsers($filters: AuthUserFiltersMany!, $sort: AuthUserSort!, $after: String, $before: String, $first: Int, $last: Int) {\n authUserFindMany(filters: $filters, sort: $sort, after: $after, before: $before, first: $first, last: $last) {\n edges {\n node {\n ...TheAuthUser\n }\n }\n totalCount\n pageInfo {\n ...PageInfo\n }\n }\n }\n ": types.TheAuthUsersDocument,
"\n mutation AuthUserCreate($data: AuthUserCreateInput!) {\n authUserCreate(data: $data) {\n ...TheAuthUser\n }\n }\n ": types.AuthUserCreateDocument,
"\n mutation AuthUserDestroyMany($ids: [String!]!) {\n authUserDestroyMany(authUserIds: $ids)\n }\n ": types.AuthUserDestroyManyDocument,
"\n mutation AuthUserDestroyMany($authUserIds: [String!]!) {\n authUserDestroyMany(authUserIds: $authUserIds)\n }\n ": types.AuthUserDestroyManyDocument,
"\n fragment PageInfo on PageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n": types.PageInfoFragmentDoc,
};

Expand Down Expand Up @@ -59,7 +59,7 @@ export function graphql(source: "\n mutation AuthUserCreate($data: AuthUser
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n mutation AuthUserDestroyMany($ids: [String!]!) {\n authUserDestroyMany(authUserIds: $ids)\n }\n "): (typeof documents)["\n mutation AuthUserDestroyMany($ids: [String!]!) {\n authUserDestroyMany(authUserIds: $ids)\n }\n "];
export function graphql(source: "\n mutation AuthUserDestroyMany($authUserIds: [String!]!) {\n authUserDestroyMany(authUserIds: $authUserIds)\n }\n "): (typeof documents)["\n mutation AuthUserDestroyMany($authUserIds: [String!]!) {\n authUserDestroyMany(authUserIds: $authUserIds)\n }\n "];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand Down
4 changes: 2 additions & 2 deletions graphql/utils/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export type AuthUserCreateMutationVariables = Exact<{
export type AuthUserCreateMutation = { __typename?: 'Mutation', authUserCreate?: { __typename?: 'AuthUser', id: string, email: string, role: AuthRole } | null };

export type AuthUserDestroyManyMutationVariables = Exact<{
ids: Array<Scalars['String']['input']> | Scalars['String']['input'];
authUserIds: Array<Scalars['String']['input']> | Scalars['String']['input'];
}>;


Expand All @@ -174,4 +174,4 @@ export const VersionDocument = {"kind":"Document","definitions":[{"kind":"Operat
export const PingDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"Ping"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ping"}}]}}]} as unknown as DocumentNode<PingMutation, PingMutationVariables>;
export const TheAuthUsersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"TheAuthUsers"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AuthUserFiltersMany"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"sort"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AuthUserSort"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"after"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"before"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"last"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authUserFindMany"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"Variable","name":{"kind":"Name","value":"sort"}}},{"kind":"Argument","name":{"kind":"Name","value":"after"},"value":{"kind":"Variable","name":{"kind":"Name","value":"after"}}},{"kind":"Argument","name":{"kind":"Name","value":"before"},"value":{"kind":"Variable","name":{"kind":"Name","value":"before"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}},{"kind":"Argument","name":{"kind":"Name","value":"last"},"value":{"kind":"Variable","name":{"kind":"Name","value":"last"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TheAuthUser"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PageInfo"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TheAuthUser"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AuthUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PageInfo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PageInfo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]} as unknown as DocumentNode<TheAuthUsersQuery, TheAuthUsersQueryVariables>;
export const AuthUserCreateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AuthUserCreate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AuthUserCreateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authUserCreate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"TheAuthUser"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TheAuthUser"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AuthUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]} as unknown as DocumentNode<AuthUserCreateMutation, AuthUserCreateMutationVariables>;
export const AuthUserDestroyManyDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AuthUserDestroyMany"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"ids"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authUserDestroyMany"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"authUserIds"},"value":{"kind":"Variable","name":{"kind":"Name","value":"ids"}}}]}]}}]} as unknown as DocumentNode<AuthUserDestroyManyMutation, AuthUserDestroyManyMutationVariables>;
export const AuthUserDestroyManyDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AuthUserDestroyMany"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"authUserIds"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authUserDestroyMany"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"authUserIds"},"value":{"kind":"Variable","name":{"kind":"Name","value":"authUserIds"}}}]}]}}]} as unknown as DocumentNode<AuthUserDestroyManyMutation, AuthUserDestroyManyMutationVariables>;
13 changes: 13 additions & 0 deletions scripts/post-deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -e

export PATH=$PATH:/opt/plesk/node/20/bin

LOG=~/logs/deploy.log

echo "Running post-deploy script" > $LOG
pnpm install >> $LOG
pnpm build >> $LOG
pnpm prisma migrate deploy >> $LOG
touch tmp/restart.txt
echo "Finished post-deploy script" >> $LOG
3 changes: 3 additions & 0 deletions scripts/server.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(async function main() {
await import("../.output/server/index.mjs");
})();
7 changes: 5 additions & 2 deletions tsconfig.server.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.server.json"
}
"extends": "./.nuxt/tsconfig.server.json",
"exclude": [
"scripts"
]
}
2 changes: 1 addition & 1 deletion ui/assets/css/colors.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
}

.text-muted {
@apply text-gray-500 dark:text-gray-400;
@apply text-gray-500;
}
}
35 changes: 23 additions & 12 deletions ui/components/actions/UActionsDropdown.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
<script setup lang="ts">
type RowAction = { label: string; title?: string; icon: string; to?: string | undefined };
const props = defineProps<{ actions: Record<string, RowAction> }>();
type RowAction = {
key: string;
label: string;
icon: string;
title?: string;
click?: () => Promise<void>;
to?: string | undefined;
};
const props = defineProps<{ actions: RowAction[][] }>();
const emit = defineEmits<{ (event: "refetch"): void }>();
const items = computed(() => [
Object.entries(props.actions).map(([key, action]) => ({
const items = props.actions.map((actionGroup) =>
actionGroup.map((action) => ({
label: action.label,
icon: action.icon,
click: () => {
if (action.to) {
click: async () => {
if (action.click) {
await action.click();
} else if (action.to) {
useRouter().push(action.to);
} else {
currentAction.value = key;
currentAction.value = action.key;
}
},
})),
]);
);
const currentAction = ref<string | null>(null);
const isShowing = (action: string) => currentAction.value === action;
Expand All @@ -32,9 +41,11 @@ const onSuccess = () => {
<UButton color="white" variant="outline" trailing-icon="i-heroicons-chevron-down" label="Actions" />
</slot>
</UDropdown>
<template v-for="(action, key) in actions" :key="key">
<UActionModal v-if="isShowing(key)" :title="action.title || action.label" @close="onClose">
<slot :name="`${key}-action`" :on-close="onClose" :on-success="onSuccess" />
</UActionModal>
<template v-for="(actionGroup, i) in actions" :key="i">
<template v-for="action in actionGroup" :key="action.key">
<UActionModal v-if="isShowing(action.key)" :title="action.title || action.label" @close="onClose">
<slot :name="`${action.key}-action`" :on-close="onClose" :on-success="onSuccess" />
</UActionModal>
</template>
</template>
</template>

0 comments on commit fb50abe

Please sign in to comment.