Skip to content

Commit

Permalink
Workshop #1
Browse files Browse the repository at this point in the history
  • Loading branch information
pziemkowski committed Nov 27, 2023
1 parent a5c2f8b commit 2158a71
Show file tree
Hide file tree
Showing 22 changed files with 212 additions and 15 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"devDependencies": {
"@apollo/client": "^3.8.4",
"@apollo/rover": "^0.19.0",
"@apollo/rover": "^0.21.0",
"@babel/preset-react": "^7.22.15",
"@graphql-codegen/cli": "^5.0.0",
"@graphql-typed-document-node/core": "^3.2.0",
Expand Down
Empty file.
8 changes: 8 additions & 0 deletions packages/backend/apps/workshops/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.contrib import admin

from . import models


@admin.register(models.WorkshopItem)
class WorkshopItemAdmin(admin.ModelAdmin):
list_display = ('id', 'name')
6 changes: 6 additions & 0 deletions packages/backend/apps/workshops/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class WorkshopsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.workshops'
29 changes: 29 additions & 0 deletions packages/backend/apps/workshops/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 4.2 on 2023-09-27 12:41

from django.db import migrations, models
import hashid_field.field


class Migration(migrations.Migration):
initial = True

dependencies = []

operations = [
migrations.CreateModel(
name='WorkshopItem',
fields=[
(
'id',
hashid_field.field.HashidAutoField(
alphabet='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
min_length=7,
prefix='',
primary_key=True,
serialize=False,
),
),
('name', models.CharField(max_length=255)),
],
),
]
Empty file.
9 changes: 9 additions & 0 deletions packages/backend/apps/workshops/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import hashid_field

from django.db import models


# Create your models here.
class WorkshopItem(models.Model):
id = hashid_field.HashidAutoField(primary_key=True)
name = models.CharField(max_length=255)
26 changes: 26 additions & 0 deletions packages/backend/apps/workshops/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import graphene

from graphene import relay
from graphene_django import DjangoObjectType

from . import models


class WorkshopItemType(DjangoObjectType):
class Meta:
model = models.WorkshopItem
interfaces = (relay.Node,)
fields = '__all__'


class WorkshopItemConnection(graphene.Connection):
class Meta:
node = WorkshopItemType


class Query(graphene.ObjectType):
all_workshop_items = graphene.relay.ConnectionField(WorkshopItemConnection)

@staticmethod
def resolve_all_workshop_items(root, info, **kwargs):
return models.WorkshopItem.objects.all()
3 changes: 3 additions & 0 deletions packages/backend/apps/workshops/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
3 changes: 3 additions & 0 deletions packages/backend/apps/workshops/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.shortcuts import render

# Create your views here.
11 changes: 10 additions & 1 deletion packages/backend/config/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,19 @@
from apps.notifications import schema as notifications_schema
from apps.users import schema as users_schema
from apps.integrations import schema as integrations_schema
from apps.workshops import schema as workshops_schema
from common.graphql.utils import graphql_query, graphql_mutation, graphql_subscription

schema = graphene.Schema(
query=graphql_query([demo_schema.Query, notifications_schema.Query, users_schema.Query, finances_schema.Query]),
query=graphql_query(
[
demo_schema.Query,
notifications_schema.Query,
users_schema.Query,
finances_schema.Query,
workshops_schema.Query,
]
),
mutation=graphql_mutation(
[
demo_schema.Mutation,
Expand Down
1 change: 1 addition & 0 deletions packages/backend/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"apps.notifications",
"apps.websockets",
"apps.integrations",
"apps.workshops",
]

INSTALLED_APPS = DJANGO_CORE_APPS + THIRD_PARTY_APPS + LOCAL_APPS
Expand Down
1 change: 0 additions & 1 deletion packages/infra/infra-shared/src/stacks/ci/ciServerless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ export class ServerlessCiConfig extends ServiceCiConfig {
build: {
commands: [
`pnpm saas workers lint`,
'pnpm saas emails build',
`pnpm saas workers test`,
],
},
Expand Down
23 changes: 21 additions & 2 deletions packages/webapp-libs/webapp-api-client/graphql/schema/api.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ that will be handled by the multipart request spec
"""
scalar Upload
type Query {
allWorkshopItems(before: String, after: String, first: Int, last: Int): WorkshopItemConnection
allSubscriptionPlans(before: String, after: String, first: Int, last: Int): StripePriceConnection
activeSubscription: SubscriptionScheduleType
allPaymentMethods(before: String, after: String, first: Int, last: Int): PaymentMethodConnection
Expand All @@ -57,11 +58,11 @@ type Query {
id: ID!
): Node
}
type StripePriceConnection {
type WorkshopItemConnection {
"Pagination data for this connection."
pageInfo: PageInfo!
"Contains the nodes in this connection."
edges: [StripePriceEdge]!
edges: [WorkshopItemEdge]!
}
"The Relay compliant `PageInfo` type, containing data necessary to paginate this connection."
type PageInfo {
Expand All @@ -74,6 +75,24 @@ type PageInfo {
"When paginating forwards, the cursor to continue."
endCursor: String
}
"A Relay edge containing a `WorkshopItem` and its cursor."
type WorkshopItemEdge {
"The item at the end of the edge"
node: WorkshopItemType
"A cursor for use in pagination"
cursor: String!
}
type WorkshopItemType implements Node {
"The ID of the object"
id: ID!
name: String!
}
type StripePriceConnection {
"Pagination data for this connection."
pageInfo: PageInfo!
"Contains the nodes in this connection."
edges: [StripePriceEdge]!
}
"A Relay edge containing a `StripePrice` and its cursor."
type StripePriceEdge {
"The item at the end of the edge"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const documents = {
"\n fragment notificationsListContentFragment on Query {\n hasUnreadNotifications\n allNotifications(first: $count, after: $cursor) {\n edges {\n node {\n id\n data\n createdAt\n readAt\n type\n issuer {\n id\n avatar\n email\n }\n }\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n": types.NotificationsListContentFragmentFragmentDoc,
"\n mutation notificationsListMarkAsReadMutation($input: MarkReadAllNotificationsMutationInput!) {\n markReadAllNotifications(input: $input) {\n ok\n }\n }\n": types.NotificationsListMarkAsReadMutationDocument,
"\n mutation authConfirmUserEmailMutation($input: ConfirmEmailMutationInput!) {\n confirm(input: $input) {\n ok\n }\n }\n": types.AuthConfirmUserEmailMutationDocument,
"\n query WorkshopItemsList {\n allWorkshopItems {\n edges {\n node {\n id\n name\n }\n }\n }\n }\n": types.WorkshopItemsListDocument,
"\n mutation authChangePasswordMutation($input: ChangePasswordMutationInput!) {\n changePassword(input: $input) {\n access\n refresh\n }\n }\n": types.AuthChangePasswordMutationDocument,
"\n mutation authUpdateUserProfileMutation($input: UpdateCurrentUserMutationInput!) {\n updateCurrentUser(input: $input) {\n userProfile {\n id\n user {\n ...commonQueryCurrentUserFragment\n }\n }\n }\n }\n": types.AuthUpdateUserProfileMutationDocument,
"\n mutation loginFormMutation($input: ObtainTokenMutationInput!) {\n tokenAuth(input: $input) {\n access\n refresh\n otpAuthToken\n }\n }\n": types.LoginFormMutationDocument,
Expand Down Expand Up @@ -289,6 +290,10 @@ export function gql(source: "\n mutation notificationsListMarkAsReadMutation($i
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n mutation authConfirmUserEmailMutation($input: ConfirmEmailMutationInput!) {\n confirm(input: $input) {\n ok\n }\n }\n"): (typeof documents)["\n mutation authConfirmUserEmailMutation($input: ConfirmEmailMutationInput!) {\n confirm(input: $input) {\n ok\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n query WorkshopItemsList {\n allWorkshopItems {\n edges {\n node {\n id\n name\n }\n }\n }\n }\n"): (typeof documents)["\n query WorkshopItemsList {\n allWorkshopItems {\n edges {\n node {\n id\n name\n }\n }\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1695,6 +1695,7 @@ export type Query = {
allNotifications?: Maybe<NotificationConnection>;
allPaymentMethods?: Maybe<PaymentMethodConnection>;
allSubscriptionPlans?: Maybe<StripePriceConnection>;
allWorkshopItems?: Maybe<WorkshopItemConnection>;
appConfig?: Maybe<AppConfig>;
appConfigCollection?: Maybe<AppConfigCollection>;
asset?: Maybe<Asset>;
Expand Down Expand Up @@ -1767,6 +1768,14 @@ export type QueryAllSubscriptionPlansArgs = {
};


export type QueryAllWorkshopItemsArgs = {
after?: InputMaybe<Scalars['String']['input']>;
before?: InputMaybe<Scalars['String']['input']>;
first?: InputMaybe<Scalars['Int']['input']>;
last?: InputMaybe<Scalars['Int']['input']>;
};


export type QueryAppConfigArgs = {
id: Scalars['String']['input'];
locale?: InputMaybe<Scalars['String']['input']>;
Expand Down Expand Up @@ -2649,6 +2658,30 @@ export type VerifyOtpMutationPayload = {
otpVerified?: Maybe<Scalars['Boolean']['output']>;
};

export type WorkshopItemConnection = {
__typename?: 'WorkshopItemConnection';
/** Contains the nodes in this connection. */
edges: Array<Maybe<WorkshopItemEdge>>;
/** Pagination data for this connection. */
pageInfo: PageInfo;
};

/** A Relay edge containing a `WorkshopItem` and its cursor. */
export type WorkshopItemEdge = {
__typename?: 'WorkshopItemEdge';
/** A cursor for use in pagination */
cursor: Scalars['String']['output'];
/** The item at the end of the edge */
node?: Maybe<WorkshopItemType>;
};

export type WorkshopItemType = Node & {
__typename?: 'WorkshopItemType';
/** The ID of the object */
id: Scalars['ID']['output'];
name: Scalars['String']['output'];
};

export type PaginationListTestQueryQueryVariables = Exact<{
first?: InputMaybe<Scalars['Int']['input']>;
after?: InputMaybe<Scalars['String']['input']>;
Expand Down Expand Up @@ -2997,6 +3030,11 @@ export type AuthConfirmUserEmailMutationMutationVariables = Exact<{

export type AuthConfirmUserEmailMutationMutation = { __typename?: 'ApiMutation', confirm?: { __typename?: 'ConfirmEmailMutationPayload', ok?: boolean | null } | null };

export type WorkshopItemsListQueryVariables = Exact<{ [key: string]: never; }>;


export type WorkshopItemsListQuery = { __typename?: 'Query', allWorkshopItems?: { __typename?: 'WorkshopItemConnection', edges: Array<{ __typename?: 'WorkshopItemEdge', node?: { __typename?: 'WorkshopItemType', id: string, name: string } | null } | null> } | null };

export type AuthChangePasswordMutationMutationVariables = Exact<{
input: ChangePasswordMutationInput;
}>;
Expand Down Expand Up @@ -3122,6 +3160,7 @@ export const NotificationsListQueryDocument = {"kind":"Document","definitions":[
export const NotificationsListSubscriptionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"notificationsListSubscription"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"notificationCreated"},"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":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"readAt"}},{"kind":"Field","name":{"kind":"Name","value":"data"}},{"kind":"Field","name":{"kind":"Name","value":"issuer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"email"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode<NotificationsListSubscriptionSubscription, NotificationsListSubscriptionSubscriptionVariables>;
export const NotificationsListMarkAsReadMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"notificationsListMarkAsReadMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"MarkReadAllNotificationsMutationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"markReadAllNotifications"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode<NotificationsListMarkAsReadMutationMutation, NotificationsListMarkAsReadMutationMutationVariables>;
export const AuthConfirmUserEmailMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"authConfirmUserEmailMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ConfirmEmailMutationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"confirm"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode<AuthConfirmUserEmailMutationMutation, AuthConfirmUserEmailMutationMutationVariables>;
export const WorkshopItemsListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"WorkshopItemsList"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"allWorkshopItems"},"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":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}}]} as unknown as DocumentNode<WorkshopItemsListQuery, WorkshopItemsListQueryVariables>;
export const AuthChangePasswordMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"authChangePasswordMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ChangePasswordMutationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"changePassword"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"access"}},{"kind":"Field","name":{"kind":"Name","value":"refresh"}}]}}]}}]} as unknown as DocumentNode<AuthChangePasswordMutationMutation, AuthChangePasswordMutationMutationVariables>;
export const AuthUpdateUserProfileMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"authUpdateUserProfileMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateCurrentUserMutationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateCurrentUser"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userProfile"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"commonQueryCurrentUserFragment"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"commonQueryCurrentUserFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CurrentUserType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}},{"kind":"Field","name":{"kind":"Name","value":"roles"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"otpVerified"}},{"kind":"Field","name":{"kind":"Name","value":"otpEnabled"}}]}}]} as unknown as DocumentNode<AuthUpdateUserProfileMutationMutation, AuthUpdateUserProfileMutationMutationVariables>;
export const LoginFormMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"loginFormMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ObtainTokenMutationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"tokenAuth"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"access"}},{"kind":"Field","name":{"kind":"Name","value":"refresh"}},{"kind":"Field","name":{"kind":"Name","value":"otpAuthToken"}}]}}]}}]} as unknown as DocumentNode<LoginFormMutationMutation, LoginFormMutationMutationVariables>;
Expand Down
3 changes: 2 additions & 1 deletion packages/webapp/src/app/app.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { Admin } from '../routes/admin';
import { PasswordReset } from '../routes/auth/passwordReset';
import ValidateOtp from '../routes/auth/validateOtp';
import { AnonymousRoute, AuthRoute } from '../shared/components/routes';
import { ConfirmEmail, Home, Login, Logout, NotFound, Profile, Signup } from './asyncComponents';
import { ConfirmEmail, Home, Login, Logout, NotFound, Profile, Signup, WorkshopItemsList } from './asyncComponents';
import { LANG_PREFIX, RoutesConfig } from './config/routes';
import { ValidRoutesProviders } from './providers';

Expand Down Expand Up @@ -65,6 +65,7 @@ export const App = () => {
<Route path={RoutesConfig.subscriptions.transactionHistory.history} element={<TransactionHistory />} />
<Route path={RoutesConfig.documents} element={<Documents />} />
<Route path={RoutesConfig.saasIdeas} element={<SaasIdeas />} />
<Route path={RoutesConfig.workshops.list} element={<WorkshopItemsList />} />
<Route path="*" element={<NotFound />} />
</Route>
<Route path={LANG_PREFIX} element={<AuthRoute allowedRoles={Role.ADMIN} />}>
Expand Down
Loading

0 comments on commit 2158a71

Please sign in to comment.