Compare commits
1 Commits
55f2023404
...
6f959b1d30
Author | SHA1 | Date | |
---|---|---|---|
|
6f959b1d30 |
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -8,7 +8,7 @@
|
|||||||
"type": "pwa-chrome",
|
"type": "pwa-chrome",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Launch Chrome against localhost",
|
"name": "Launch Chrome against localhost",
|
||||||
"url": "http://user.localhost",
|
"url": "http://blog.localhost",
|
||||||
"webRoot": "${workspaceFolder}",
|
"webRoot": "${workspaceFolder}",
|
||||||
"userDataDir": "/Users/ivan/Projects/.chrome"
|
"userDataDir": "/Users/ivan/Projects/.chrome"
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
client: {
|
client: {
|
||||||
service: {
|
service: {
|
||||||
name: "auth-center",
|
name: 'blog-be',
|
||||||
url: "http://localhost:7152/graphql",
|
url: 'http://api.blog.localhost/graphql'
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
overwrite: true
|
overwrite: true
|
||||||
schema: "http://localhost:7152/graphql"
|
schema: "http://localhost:7132/graphql"
|
||||||
generates:
|
generates:
|
||||||
commons/graphql/generated.tsx:
|
commons/graphql/generated.tsx:
|
||||||
plugins:
|
plugins:
|
||||||
|
@ -14,18 +14,22 @@ export type Scalars = {
|
|||||||
DateTime: any;
|
DateTime: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Account = {
|
export type Article = {
|
||||||
__typename?: 'Account';
|
__typename?: 'Article';
|
||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
name: Scalars['String'];
|
title: Scalars['String'];
|
||||||
nick: Scalars['String'];
|
content: Scalars['String'];
|
||||||
password: Scalars['String'];
|
publishedAt?: Maybe<Scalars['DateTime']>;
|
||||||
registeredAt: Scalars['DateTime'];
|
tags: Array<Scalars['String']>;
|
||||||
|
html: Scalars['String'];
|
||||||
|
description?: Maybe<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateAccountInput = {
|
export type CreateArticleInput = {
|
||||||
name: Scalars['String'];
|
title: Scalars['String'];
|
||||||
password: Scalars['String'];
|
content: Scalars['String'];
|
||||||
|
publishedAt?: Maybe<Scalars['DateTime']>;
|
||||||
|
tags: Array<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -34,62 +38,44 @@ export type Hello = {
|
|||||||
message: Scalars['String'];
|
message: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LoggedInfo = {
|
|
||||||
__typename?: 'LoggedInfo';
|
|
||||||
account: Account;
|
|
||||||
/** jwt, access application */
|
|
||||||
accessToken: Scalars['String'];
|
|
||||||
/** jwt, refresh token in auth center */
|
|
||||||
refreshToken: Scalars['String'];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type LoginInput = {
|
|
||||||
name: Scalars['String'];
|
|
||||||
password: Scalars['String'];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Mutation = {
|
export type Mutation = {
|
||||||
__typename?: 'Mutation';
|
__typename?: 'Mutation';
|
||||||
createAccount: Account;
|
createArticle: Article;
|
||||||
updateAccount: Account;
|
updateArticle: Article;
|
||||||
removeAccount: Account;
|
removeArticle: Scalars['Int'];
|
||||||
login: LoggedInfo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateAccountArgs = {
|
export type MutationCreateArticleArgs = {
|
||||||
createAccountInput: CreateAccountInput;
|
createArticleInput: CreateArticleInput;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationUpdateAccountArgs = {
|
export type MutationUpdateArticleArgs = {
|
||||||
updateAccountInput: UpdateAccountInput;
|
updateArticleInput: UpdateArticleInput;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationRemoveAccountArgs = {
|
export type MutationRemoveArticleArgs = {
|
||||||
id: Scalars['String'];
|
id: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationLoginArgs = {
|
|
||||||
loginInput: LoginInput;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Query = {
|
export type Query = {
|
||||||
__typename?: 'Query';
|
__typename?: 'Query';
|
||||||
hello: Hello;
|
hello: Hello;
|
||||||
accounts: Array<Account>;
|
articles: Array<Article>;
|
||||||
account: Account;
|
article: Article;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type QueryAccountArgs = {
|
export type QueryArticleArgs = {
|
||||||
id: Scalars['String'];
|
id: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateAccountInput = {
|
export type UpdateArticleInput = {
|
||||||
name?: Maybe<Scalars['String']>;
|
title?: Maybe<Scalars['String']>;
|
||||||
password?: Maybe<Scalars['String']>;
|
content?: Maybe<Scalars['String']>;
|
||||||
|
publishedAt?: Maybe<Scalars['DateTime']>;
|
||||||
|
tags?: Maybe<Array<Scalars['String']>>;
|
||||||
id: Scalars['String'];
|
id: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"kind": "OBJECT",
|
"kind": "OBJECT",
|
||||||
"name": "Account",
|
"name": "Article",
|
||||||
"description": null,
|
"description": null,
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "name",
|
"name": "title",
|
||||||
"description": null,
|
"description": null,
|
||||||
"args": [],
|
"args": [],
|
||||||
"type": {
|
"type": {
|
||||||
@ -46,7 +46,7 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "nick",
|
"name": "content",
|
||||||
"description": null,
|
"description": null,
|
||||||
"args": [],
|
"args": [],
|
||||||
"type": {
|
"type": {
|
||||||
@ -62,7 +62,43 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "password",
|
"name": "publishedAt",
|
||||||
|
"description": null,
|
||||||
|
"args": [],
|
||||||
|
"type": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "DateTime",
|
||||||
|
"ofType": null
|
||||||
|
},
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tags",
|
||||||
|
"description": null,
|
||||||
|
"args": [],
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "LIST",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "html",
|
||||||
"description": null,
|
"description": null,
|
||||||
"args": [],
|
"args": [],
|
||||||
"type": {
|
"type": {
|
||||||
@ -78,17 +114,13 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "registeredAt",
|
"name": "description",
|
||||||
"description": null,
|
"description": null,
|
||||||
"args": [],
|
"args": [],
|
||||||
"type": {
|
"type": {
|
||||||
"kind": "NON_NULL",
|
"kind": "SCALAR",
|
||||||
"name": null,
|
"name": "String",
|
||||||
"ofType": {
|
"ofType": null
|
||||||
"kind": "SCALAR",
|
|
||||||
"name": "DateTime",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"isDeprecated": false,
|
"isDeprecated": false,
|
||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
@ -121,12 +153,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "INPUT_OBJECT",
|
"kind": "INPUT_OBJECT",
|
||||||
"name": "CreateAccountInput",
|
"name": "CreateArticleInput",
|
||||||
"description": null,
|
"description": null,
|
||||||
"fields": null,
|
"fields": null,
|
||||||
"inputFields": [
|
"inputFields": [
|
||||||
{
|
{
|
||||||
"name": "name",
|
"name": "title",
|
||||||
"description": null,
|
"description": null,
|
||||||
"type": {
|
"type": {
|
||||||
"kind": "NON_NULL",
|
"kind": "NON_NULL",
|
||||||
@ -142,7 +174,7 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "password",
|
"name": "content",
|
||||||
"description": null,
|
"description": null,
|
||||||
"type": {
|
"type": {
|
||||||
"kind": "NON_NULL",
|
"kind": "NON_NULL",
|
||||||
@ -156,6 +188,42 @@
|
|||||||
"defaultValue": null,
|
"defaultValue": null,
|
||||||
"isDeprecated": false,
|
"isDeprecated": false,
|
||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "publishedAt",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "DateTime",
|
||||||
|
"ofType": null
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tags",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "LIST",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"interfaces": null,
|
"interfaces": null,
|
||||||
@ -199,126 +267,24 @@
|
|||||||
"enumValues": null,
|
"enumValues": null,
|
||||||
"possibleTypes": null
|
"possibleTypes": null
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"kind": "OBJECT",
|
|
||||||
"name": "LoggedInfo",
|
|
||||||
"description": null,
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "account",
|
|
||||||
"description": null,
|
|
||||||
"args": [],
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "OBJECT",
|
|
||||||
"name": "Account",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isDeprecated": false,
|
|
||||||
"deprecationReason": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "accessToken",
|
|
||||||
"description": "jwt, access application",
|
|
||||||
"args": [],
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "SCALAR",
|
|
||||||
"name": "String",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isDeprecated": false,
|
|
||||||
"deprecationReason": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "refreshToken",
|
|
||||||
"description": "jwt, refresh token in auth center",
|
|
||||||
"args": [],
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "SCALAR",
|
|
||||||
"name": "String",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isDeprecated": false,
|
|
||||||
"deprecationReason": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"inputFields": null,
|
|
||||||
"interfaces": [],
|
|
||||||
"enumValues": null,
|
|
||||||
"possibleTypes": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "INPUT_OBJECT",
|
|
||||||
"name": "LoginInput",
|
|
||||||
"description": null,
|
|
||||||
"fields": null,
|
|
||||||
"inputFields": [
|
|
||||||
{
|
|
||||||
"name": "name",
|
|
||||||
"description": null,
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "SCALAR",
|
|
||||||
"name": "String",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultValue": null,
|
|
||||||
"isDeprecated": false,
|
|
||||||
"deprecationReason": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "password",
|
|
||||||
"description": null,
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "SCALAR",
|
|
||||||
"name": "String",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultValue": null,
|
|
||||||
"isDeprecated": false,
|
|
||||||
"deprecationReason": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"interfaces": null,
|
|
||||||
"enumValues": null,
|
|
||||||
"possibleTypes": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"kind": "OBJECT",
|
"kind": "OBJECT",
|
||||||
"name": "Mutation",
|
"name": "Mutation",
|
||||||
"description": null,
|
"description": null,
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "createAccount",
|
"name": "createArticle",
|
||||||
"description": null,
|
"description": null,
|
||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
"name": "createAccountInput",
|
"name": "createArticleInput",
|
||||||
"description": null,
|
"description": null,
|
||||||
"type": {
|
"type": {
|
||||||
"kind": "NON_NULL",
|
"kind": "NON_NULL",
|
||||||
"name": null,
|
"name": null,
|
||||||
"ofType": {
|
"ofType": {
|
||||||
"kind": "INPUT_OBJECT",
|
"kind": "INPUT_OBJECT",
|
||||||
"name": "CreateAccountInput",
|
"name": "CreateArticleInput",
|
||||||
"ofType": null
|
"ofType": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -332,7 +298,7 @@
|
|||||||
"name": null,
|
"name": null,
|
||||||
"ofType": {
|
"ofType": {
|
||||||
"kind": "OBJECT",
|
"kind": "OBJECT",
|
||||||
"name": "Account",
|
"name": "Article",
|
||||||
"ofType": null
|
"ofType": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -340,18 +306,18 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "updateAccount",
|
"name": "updateArticle",
|
||||||
"description": null,
|
"description": null,
|
||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
"name": "updateAccountInput",
|
"name": "updateArticleInput",
|
||||||
"description": null,
|
"description": null,
|
||||||
"type": {
|
"type": {
|
||||||
"kind": "NON_NULL",
|
"kind": "NON_NULL",
|
||||||
"name": null,
|
"name": null,
|
||||||
"ofType": {
|
"ofType": {
|
||||||
"kind": "INPUT_OBJECT",
|
"kind": "INPUT_OBJECT",
|
||||||
"name": "UpdateAccountInput",
|
"name": "UpdateArticleInput",
|
||||||
"ofType": null
|
"ofType": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -365,7 +331,7 @@
|
|||||||
"name": null,
|
"name": null,
|
||||||
"ofType": {
|
"ofType": {
|
||||||
"kind": "OBJECT",
|
"kind": "OBJECT",
|
||||||
"name": "Account",
|
"name": "Article",
|
||||||
"ofType": null
|
"ofType": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -373,7 +339,7 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "removeAccount",
|
"name": "removeArticle",
|
||||||
"description": null,
|
"description": null,
|
||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
@ -397,41 +363,8 @@
|
|||||||
"kind": "NON_NULL",
|
"kind": "NON_NULL",
|
||||||
"name": null,
|
"name": null,
|
||||||
"ofType": {
|
"ofType": {
|
||||||
"kind": "OBJECT",
|
"kind": "SCALAR",
|
||||||
"name": "Account",
|
"name": "Int",
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isDeprecated": false,
|
|
||||||
"deprecationReason": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "login",
|
|
||||||
"description": null,
|
|
||||||
"args": [
|
|
||||||
{
|
|
||||||
"name": "loginInput",
|
|
||||||
"description": null,
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "INPUT_OBJECT",
|
|
||||||
"name": "LoginInput",
|
|
||||||
"ofType": null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultValue": null,
|
|
||||||
"isDeprecated": false,
|
|
||||||
"deprecationReason": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"type": {
|
|
||||||
"kind": "NON_NULL",
|
|
||||||
"name": null,
|
|
||||||
"ofType": {
|
|
||||||
"kind": "OBJECT",
|
|
||||||
"name": "LoggedInfo",
|
|
||||||
"ofType": null
|
"ofType": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -444,6 +377,16 @@
|
|||||||
"enumValues": null,
|
"enumValues": null,
|
||||||
"possibleTypes": null
|
"possibleTypes": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "Int",
|
||||||
|
"description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.",
|
||||||
|
"fields": null,
|
||||||
|
"inputFields": null,
|
||||||
|
"interfaces": null,
|
||||||
|
"enumValues": null,
|
||||||
|
"possibleTypes": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"kind": "OBJECT",
|
"kind": "OBJECT",
|
||||||
"name": "Query",
|
"name": "Query",
|
||||||
@ -466,7 +409,7 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "accounts",
|
"name": "articles",
|
||||||
"description": null,
|
"description": null,
|
||||||
"args": [],
|
"args": [],
|
||||||
"type": {
|
"type": {
|
||||||
@ -480,7 +423,7 @@
|
|||||||
"name": null,
|
"name": null,
|
||||||
"ofType": {
|
"ofType": {
|
||||||
"kind": "OBJECT",
|
"kind": "OBJECT",
|
||||||
"name": "Account",
|
"name": "Article",
|
||||||
"ofType": null
|
"ofType": null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -490,7 +433,7 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "account",
|
"name": "article",
|
||||||
"description": null,
|
"description": null,
|
||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
@ -515,7 +458,7 @@
|
|||||||
"name": null,
|
"name": null,
|
||||||
"ofType": {
|
"ofType": {
|
||||||
"kind": "OBJECT",
|
"kind": "OBJECT",
|
||||||
"name": "Account",
|
"name": "Article",
|
||||||
"ofType": null
|
"ofType": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -530,12 +473,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "INPUT_OBJECT",
|
"kind": "INPUT_OBJECT",
|
||||||
"name": "UpdateAccountInput",
|
"name": "UpdateArticleInput",
|
||||||
"description": null,
|
"description": null,
|
||||||
"fields": null,
|
"fields": null,
|
||||||
"inputFields": [
|
"inputFields": [
|
||||||
{
|
{
|
||||||
"name": "name",
|
"name": "title",
|
||||||
"description": null,
|
"description": null,
|
||||||
"type": {
|
"type": {
|
||||||
"kind": "SCALAR",
|
"kind": "SCALAR",
|
||||||
@ -547,7 +490,7 @@
|
|||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "password",
|
"name": "content",
|
||||||
"description": null,
|
"description": null,
|
||||||
"type": {
|
"type": {
|
||||||
"kind": "SCALAR",
|
"kind": "SCALAR",
|
||||||
@ -558,6 +501,38 @@
|
|||||||
"isDeprecated": false,
|
"isDeprecated": false,
|
||||||
"deprecationReason": null
|
"deprecationReason": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "publishedAt",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "DateTime",
|
||||||
|
"ofType": null
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tags",
|
||||||
|
"description": null,
|
||||||
|
"type": {
|
||||||
|
"kind": "LIST",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "NON_NULL",
|
||||||
|
"name": null,
|
||||||
|
"ofType": {
|
||||||
|
"kind": "SCALAR",
|
||||||
|
"name": "String",
|
||||||
|
"ofType": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultValue": null,
|
||||||
|
"isDeprecated": false,
|
||||||
|
"deprecationReason": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "id",
|
"name": "id",
|
||||||
"description": null,
|
"description": null,
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
.wrapper {
|
.wrapper {
|
||||||
@apply bg-green-400 text-white min-h-screen;
|
@apply bg-green-400 text-white min-h-screen;
|
||||||
|
@apply absolute top-0 left-0 right-0 bottom-0 sm:static;
|
||||||
|
@apply -translate-x-full transform transition-transform sm:transition-none sm:translate-x-0;
|
||||||
:global(.dark) & {
|
:global(.dark) & {
|
||||||
@apply bg-gray-800 text-gray-400;
|
@apply bg-gray-800 text-gray-400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.focusOpen {
|
||||||
|
@apply translate-x-0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.sidebar {
|
.sidebar {
|
||||||
@apply overflow-hidden flex flex-col fixed top-0;
|
@apply overflow-hidden flex flex-col fixed top-0;
|
||||||
@ -11,8 +17,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
@apply w-16 h-16;
|
@apply w-36 h-36 rounded-full;
|
||||||
@apply md:w-36 md:h-36 rounded-full;
|
@apply sm:w-16 sm:h-16;
|
||||||
|
@apply md:w-36 md:h-36;
|
||||||
@apply mx-auto md:my-8 flex-none;
|
@apply mx-auto md:my-8 flex-none;
|
||||||
|
|
||||||
:global(.dark) & {
|
:global(.dark) & {
|
||||||
@ -21,14 +28,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
@apply md:text-3xl md:tracking-wide font-mono;
|
@apply sm:text-base md:text-3xl text-3xl md:tracking-wide font-mono;
|
||||||
@apply md:my-8 my-4 flex-none select-all;
|
@apply md:my-8 my-4 flex-none select-all;
|
||||||
}
|
}
|
||||||
.nav {
|
.nav {
|
||||||
@apply my-auto text-left self-center;
|
@apply my-auto text-left self-center;
|
||||||
}
|
}
|
||||||
.navItem {
|
.navItem {
|
||||||
@apply leading-8 md:text-lg cursor-pointer my-2;
|
@apply leading-8 md:text-lg sm:text-base text-lg cursor-pointer my-2;
|
||||||
@apply tracking-widest;
|
@apply tracking-widest;
|
||||||
small {
|
small {
|
||||||
@apply text-xs md:inline hidden;
|
@apply text-xs md:inline hidden;
|
@ -1,19 +1,28 @@
|
|||||||
import React, { FC } from "react";
|
import React, { FC, MouseEventHandler } from "react";
|
||||||
import styles from "./global-layout.module.css";
|
import styles from "./global-sidebar.module.css";
|
||||||
import Image from "next/image";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import classnames from 'classnames';
|
import classnames from "classnames";
|
||||||
|
|
||||||
const fullName = `${process.env.NEXT_PUBLIC_FIRST_NAME} ${process.env.NEXT_PUBLIC_LAST_NAME}`;
|
const fullName = `${process.env.NEXT_PUBLIC_FIRST_NAME} ${process.env.NEXT_PUBLIC_LAST_NAME}`;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className: string;
|
className: string;
|
||||||
|
focusOpen?: boolean;
|
||||||
|
onClick?: MouseEventHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GlobalSidebar: FC<Props> = ({className}) => {
|
export const GlobalSidebar: FC<Props> = ({
|
||||||
|
className,
|
||||||
|
focusOpen = false,
|
||||||
|
onClick,
|
||||||
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className={classnames(className, styles.wrapper)}>
|
<div
|
||||||
|
className={classnames(className, styles.wrapper, {
|
||||||
|
[styles.focusOpen]: focusOpen,
|
||||||
|
})}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
<aside className={classnames(className, styles.sidebar)}>
|
<aside className={classnames(className, styles.sidebar)}>
|
||||||
<img className={styles.avatar} src="/images/avatar.png" />
|
<img className={styles.avatar} src="/images/avatar.png" />
|
||||||
<h2 className={styles.name}>{fullName}</h2>
|
<h2 className={styles.name}>{fullName}</h2>
|
||||||
|
7499
package-lock.json
generated
7499
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "launch-fs",
|
"name": "blog-fs",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -p 7153",
|
"dev": "next dev -p 7133",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start -p 7153",
|
"start": "next start -p 7133",
|
||||||
"predev": "npm run generate",
|
"predev": "npm run generate",
|
||||||
"generate": "graphql-codegen --config codegen.yml"
|
"generate": "graphql-codegen --config codegen.yml"
|
||||||
},
|
},
|
||||||
@ -14,14 +14,11 @@
|
|||||||
"@fortawesome/fontawesome-svg-core": "^1.2.35",
|
"@fortawesome/fontawesome-svg-core": "^1.2.35",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.15.3",
|
"@fortawesome/free-solid-svg-icons": "^5.15.3",
|
||||||
"@fortawesome/react-fontawesome": "^0.1.14",
|
"@fortawesome/react-fontawesome": "^0.1.14",
|
||||||
"@material-ui/core": "^4.12.0",
|
|
||||||
"@material-ui/icons": "^4.11.2",
|
|
||||||
"apollo-link-scalars": "^2.1.3",
|
"apollo-link-scalars": "^2.1.3",
|
||||||
"babel-plugin-superjson-next": "^0.3.0",
|
"babel-plugin-superjson-next": "^0.3.0",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
"clsx": "^1.1.1",
|
||||||
"date-fns": "^2.22.1",
|
"date-fns": "^2.22.1",
|
||||||
"formik": "^2.2.9",
|
|
||||||
"formik-material-ui": "^3.0.1",
|
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"graphql-scalars": "^1.10.0",
|
"graphql-scalars": "^1.10.0",
|
||||||
"highlight.js": "^11.0.1",
|
"highlight.js": "^11.0.1",
|
||||||
@ -31,8 +28,7 @@
|
|||||||
"ramda": "^0.27.1",
|
"ramda": "^0.27.1",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"superjson": "^1.7.4",
|
"superjson": "^1.7.4"
|
||||||
"yup": "^0.32.9"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@graphql-codegen/cli": "1.21.4",
|
"@graphql-codegen/cli": "1.21.4",
|
||||||
|
@ -1,3 +1,35 @@
|
|||||||
.page {
|
.page {
|
||||||
@apply flex bg-gray-300 min-h-screen h-full;
|
@apply flex;
|
||||||
|
}
|
||||||
|
.sidebar {
|
||||||
|
@apply w-full md:w-64 sm:w-32 flex-none;
|
||||||
|
}
|
||||||
|
.primary {
|
||||||
|
@apply flex-auto w-screen min-w-0;
|
||||||
|
@apply bg-gray-100 text-gray-700;
|
||||||
|
:global(.dark) & {
|
||||||
|
@apply bg-gray-700 text-gray-300;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
@apply mx-auto max-w-screen-lg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pageHeader {
|
||||||
|
@apply p-3 bg-gray-50 flex justify-between;
|
||||||
|
|
||||||
|
:global(.dark) & {
|
||||||
|
@apply bg-gray-800;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.headerBtn {
|
||||||
|
@apply sm:hidden text-green-400;
|
||||||
|
@apply w-4 h-4 p-0 focus:outline-none;
|
||||||
|
|
||||||
|
&.opened {
|
||||||
|
@apply text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
@apply absolute;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,18 +1,53 @@
|
|||||||
import "../styles/globals.css";
|
import "../styles/globals.css";
|
||||||
import "tailwindcss/tailwind.css";
|
import "tailwindcss/tailwind.css";
|
||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
|
import { GlobalSidebar } from "../components/layouts/global-sidebar";
|
||||||
import styles from "./_app.module.css";
|
import styles from "./_app.module.css";
|
||||||
import { ApolloProvider } from "@apollo/client";
|
import { ApolloProvider } from "@apollo/client";
|
||||||
import { useApollo } from "../commons/graphql/client";
|
import { useApollo } from "../commons/graphql/client";
|
||||||
import { ThemeProvider } from "../commons/theme";
|
import { ThemeProvider, useTheme } from "../commons/theme";
|
||||||
|
import { SwitchTheme } from "../components/switch-theme";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import {
|
||||||
|
faCross,
|
||||||
|
faHamburger,
|
||||||
|
faTimes,
|
||||||
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import clsx from "clsx";
|
||||||
|
|
||||||
function MyApp({ Component, pageProps }) {
|
function MyApp({ Component, pageProps }) {
|
||||||
const apolloClient = useApollo(pageProps);
|
const apolloClient = useApollo(pageProps);
|
||||||
|
const [focusOpenSidebar, setFocusOpenSidebar] = useState(false);
|
||||||
return (
|
return (
|
||||||
<ApolloProvider client={apolloClient}>
|
<ApolloProvider client={apolloClient}>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<div className={styles.page}>
|
<div className={styles.page}>
|
||||||
<Component {...pageProps} />
|
<GlobalSidebar
|
||||||
|
className={styles.sidebar}
|
||||||
|
focusOpen={focusOpenSidebar}
|
||||||
|
onClick={() => setFocusOpenSidebar(false)}
|
||||||
|
/>
|
||||||
|
<div className={styles.primary}>
|
||||||
|
<header className={styles.pageHeader}>
|
||||||
|
<button
|
||||||
|
className={clsx(styles.headerBtn, {
|
||||||
|
[styles.opened]: focusOpenSidebar,
|
||||||
|
})}
|
||||||
|
onClick={() => setFocusOpenSidebar(!focusOpenSidebar)}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={focusOpenSidebar ? faTimes : faHamburger}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<h1>{"Ivan Li 的个人博客"}</h1>
|
||||||
|
<div className={styles.actions}>
|
||||||
|
<SwitchTheme />
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</ApolloProvider>
|
</ApolloProvider>
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import Document, { Html, Head, Main, NextScript } from "next/document";
|
|
||||||
import { ServerStyleSheets } from "@material-ui/core/styles";
|
|
||||||
|
|
||||||
export default class MyDocument extends Document {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Html lang="en">
|
|
||||||
<Head>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
|
|
||||||
/>
|
|
||||||
</Head>
|
|
||||||
<body>
|
|
||||||
<Main />
|
|
||||||
<NextScript />
|
|
||||||
</body>
|
|
||||||
</Html>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// `getInitialProps` belongs to `_document` (instead of `_app`),
|
|
||||||
// it's compatible with server-side generation (SSG).
|
|
||||||
MyDocument.getInitialProps = async (ctx) => {
|
|
||||||
// Resolution order
|
|
||||||
//
|
|
||||||
// On the server:
|
|
||||||
// 1. app.getInitialProps
|
|
||||||
// 2. page.getInitialProps
|
|
||||||
// 3. document.getInitialProps
|
|
||||||
// 4. app.render
|
|
||||||
// 5. page.render
|
|
||||||
// 6. document.render
|
|
||||||
//
|
|
||||||
// On the server with error:
|
|
||||||
// 1. document.getInitialProps
|
|
||||||
// 2. app.render
|
|
||||||
// 3. page.render
|
|
||||||
// 4. document.render
|
|
||||||
//
|
|
||||||
// On the client
|
|
||||||
// 1. app.getInitialProps
|
|
||||||
// 2. page.getInitialProps
|
|
||||||
// 3. app.render
|
|
||||||
// 4. page.render
|
|
||||||
|
|
||||||
// Render app and page and get the context of the page with collected side effects.
|
|
||||||
const sheets = new ServerStyleSheets();
|
|
||||||
const originalRenderPage = ctx.renderPage;
|
|
||||||
|
|
||||||
ctx.renderPage = () =>
|
|
||||||
originalRenderPage({
|
|
||||||
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
|
|
||||||
});
|
|
||||||
|
|
||||||
const initialProps = await Document.getInitialProps(ctx);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...initialProps,
|
|
||||||
// Styles fragment is rendered after the app and page rendering finish.
|
|
||||||
styles: [
|
|
||||||
...React.Children.toArray(initialProps.styles),
|
|
||||||
sheets.getStyleElement(),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
54
pages/articles/[id].tsx
Normal file
54
pages/articles/[id].tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import styles from "./article.module.css";
|
||||||
|
import { GetServerSideProps } from "next";
|
||||||
|
import { addApolloState, initializeApollo } from "../../commons/graphql/client";
|
||||||
|
import { ARTICLE } from "../../commons/graphql/queries";
|
||||||
|
import { Article } from "../../commons/graphql/generated";
|
||||||
|
import { formatRelative } from "date-fns";
|
||||||
|
import { zhCN } from "date-fns/locale";
|
||||||
|
interface Props {
|
||||||
|
article: Article;
|
||||||
|
}
|
||||||
|
const ArticleDetails: FC<Props> = ({ article }) => {
|
||||||
|
// const router = useRouter()
|
||||||
|
// const { data } = useQuery<{ article: Article }>(ARTICLE, {
|
||||||
|
// variables: router.query,
|
||||||
|
// });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className={styles.articleDetails}>
|
||||||
|
<article className={styles.article}>
|
||||||
|
<header>
|
||||||
|
<h1>{article.title}</h1>
|
||||||
|
<div className={styles.headerInfo}>
|
||||||
|
<address>作者 Ivan Li,发布于 </address>
|
||||||
|
<time>
|
||||||
|
{formatRelative(article.publishedAt, new Date(), {
|
||||||
|
locale: zhCN,
|
||||||
|
})}
|
||||||
|
</time>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: article.html }}></div>
|
||||||
|
<footer>
|
||||||
|
<div className={styles.articleEnd}>The End</div>
|
||||||
|
</footer>
|
||||||
|
</article>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
|
||||||
|
const apolloClient = initializeApollo();
|
||||||
|
|
||||||
|
const { data } = await apolloClient.query<{ article: Article }>({
|
||||||
|
query: ARTICLE,
|
||||||
|
variables: params,
|
||||||
|
});
|
||||||
|
|
||||||
|
return addApolloState(apolloClient, {
|
||||||
|
props: { article: data.article },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ArticleDetails;
|
382
pages/articles/article.module.css
Normal file
382
pages/articles/article.module.css
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
.articleDetail {
|
||||||
|
}
|
||||||
|
.article {
|
||||||
|
@apply bg-gray-50 md:mx-2 overflow-hidden rounded-xl my-6;
|
||||||
|
|
||||||
|
:global(.dark) & {
|
||||||
|
@apply bg-gray-800;
|
||||||
|
}
|
||||||
|
& > header {
|
||||||
|
@apply my-8 mx-4;
|
||||||
|
h1 {
|
||||||
|
@apply text-2xl md:text-4xl font-medium mb-4;
|
||||||
|
|
||||||
|
:global(.dark) & {
|
||||||
|
@apply text-gray-200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > div {
|
||||||
|
@apply my-4 leading-8 mx-4 lg:mx-6 xl:mx-8 text-justify;
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4 {
|
||||||
|
@apply text-red-400;
|
||||||
|
|
||||||
|
:global(.dark) & {
|
||||||
|
@apply text-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
@apply hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
@apply text-2xl mt-8 mb-4 font-semibold border-b border-red-500 leading-10;
|
||||||
|
|
||||||
|
:global(.dark) & {
|
||||||
|
@apply border-green-700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
@apply text-xl mt-6 mb-2 font-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
@apply mt-4 font-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
@apply my-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
@apply pl-4;
|
||||||
|
|
||||||
|
li {
|
||||||
|
@apply list-disc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ol {
|
||||||
|
@apply pl-4;
|
||||||
|
|
||||||
|
li {
|
||||||
|
@apply list-decimal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
@apply text-red-400 underline;
|
||||||
|
|
||||||
|
:global(.dark) & {
|
||||||
|
@apply text-green-500;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
@apply filter saturate-200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code,
|
||||||
|
pre {
|
||||||
|
@apply font-mono rounded;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
@apply bg-gray-400 bg-opacity-10 px-4 overflow-hidden border-l-2 border-green-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
code:not(:global(.hljs)) {
|
||||||
|
@apply p-1 text-red-500 bg-red-100;
|
||||||
|
:global(.dark) & {
|
||||||
|
@apply bg-green-800 bg-opacity-20 text-green-400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
code:global(.hljs) {
|
||||||
|
@apply text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global {
|
||||||
|
:not(:global(.dark)) & {
|
||||||
|
pre code.hljs {
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.hljs {
|
||||||
|
padding: 3px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
color: #68615e;
|
||||||
|
background: #f1efee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs ::selection {
|
||||||
|
color: #a8a19f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* purposely do not highlight these things */
|
||||||
|
.hljs-formula,
|
||||||
|
.hljs-params,
|
||||||
|
.hljs-property {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base03 - #9c9491 - Comments, Invisibles, Line Highlighting */
|
||||||
|
.hljs-comment {
|
||||||
|
color: #9c9491;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base04 - #766e6b - Dark Foreground (Used for status bars) */
|
||||||
|
.hljs-tag {
|
||||||
|
color: #766e6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base05 - #68615e - Default Foreground, Caret, Delimiters, Operators */
|
||||||
|
.hljs-subst,
|
||||||
|
.hljs-punctuation,
|
||||||
|
.hljs-operator {
|
||||||
|
color: #68615e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-operator {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted */
|
||||||
|
.hljs-bullet,
|
||||||
|
.hljs-variable,
|
||||||
|
.hljs-template-variable,
|
||||||
|
.hljs-selector-tag,
|
||||||
|
.hljs-name,
|
||||||
|
.hljs-deletion {
|
||||||
|
color: #f22c40;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url */
|
||||||
|
.hljs-symbol,
|
||||||
|
.hljs-number,
|
||||||
|
.hljs-link,
|
||||||
|
.hljs-attr,
|
||||||
|
.hljs-variable.constant_,
|
||||||
|
.hljs-literal {
|
||||||
|
color: #df5320;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0A - Classes, Markup Bold, Search Text Background */
|
||||||
|
.hljs-title,
|
||||||
|
.hljs-class .hljs-title,
|
||||||
|
.hljs-title.class_ {
|
||||||
|
color: #c38418;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-strong {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #c38418;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0B - Strings, Inherited Class, Markup Code, Diff Inserted */
|
||||||
|
.hljs-code,
|
||||||
|
.hljs-addition,
|
||||||
|
.hljs-title.class_.inherited__,
|
||||||
|
.hljs-string {
|
||||||
|
color: #7b9726;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0C - Support, Regular Expressions, Escape Characters, Markup Quotes */
|
||||||
|
.hljs-built_in,
|
||||||
|
.hljs-doctag,
|
||||||
|
.hljs-quote,
|
||||||
|
.hljs-keyword.hljs-atrule,
|
||||||
|
.hljs-regexp {
|
||||||
|
color: #3d97b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0D - Functions, Methods, Attribute IDs, Headings */
|
||||||
|
.hljs-function .hljs-title,
|
||||||
|
.hljs-attribute,
|
||||||
|
.ruby .hljs-property,
|
||||||
|
.hljs-title.function_,
|
||||||
|
.hljs-section {
|
||||||
|
color: #407ee7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed */
|
||||||
|
.hljs-type,
|
||||||
|
.hljs-template-tag,
|
||||||
|
.diff .hljs-meta,
|
||||||
|
.hljs-keyword {
|
||||||
|
color: #6666ea;
|
||||||
|
}
|
||||||
|
.hljs-emphasis {
|
||||||
|
color: #6666ea;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. <?php ?> */
|
||||||
|
.hljs-meta,
|
||||||
|
.hljs-meta .hljs-keyword,
|
||||||
|
.hljs-meta .hljs-string {
|
||||||
|
color: #c33ff3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-meta .hljs-keyword,
|
||||||
|
.hljs-meta-keyword {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:global(.dark) & {
|
||||||
|
pre code.hljs {
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.hljs {
|
||||||
|
padding: 3px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
color: #929181;
|
||||||
|
background: #22221b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs ::selection {
|
||||||
|
color: #5f5e4e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* purposely do not highlight these things */
|
||||||
|
.hljs-formula,
|
||||||
|
.hljs-params,
|
||||||
|
.hljs-property {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base03 - #6c6b5a - Comments, Invisibles, Line Highlighting */
|
||||||
|
.hljs-comment {
|
||||||
|
color: #6c6b5a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base04 - #878573 - Dark Foreground (Used for status bars) */
|
||||||
|
.hljs-tag {
|
||||||
|
color: #878573;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base05 - #929181 - Default Foreground, Caret, Delimiters, Operators */
|
||||||
|
.hljs-subst,
|
||||||
|
.hljs-punctuation,
|
||||||
|
.hljs-operator {
|
||||||
|
color: #929181;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-operator {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted */
|
||||||
|
.hljs-bullet,
|
||||||
|
.hljs-variable,
|
||||||
|
.hljs-template-variable,
|
||||||
|
.hljs-selector-tag,
|
||||||
|
.hljs-name,
|
||||||
|
.hljs-deletion {
|
||||||
|
color: #ba6236;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url */
|
||||||
|
.hljs-symbol,
|
||||||
|
.hljs-number,
|
||||||
|
.hljs-link,
|
||||||
|
.hljs-attr,
|
||||||
|
.hljs-variable.constant_,
|
||||||
|
.hljs-literal {
|
||||||
|
color: #ae7313;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0A - Classes, Markup Bold, Search Text Background */
|
||||||
|
.hljs-title,
|
||||||
|
.hljs-class .hljs-title,
|
||||||
|
.hljs-title.class_ {
|
||||||
|
color: #a5980d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-strong {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #a5980d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0B - Strings, Inherited Class, Markup Code, Diff Inserted */
|
||||||
|
.hljs-code,
|
||||||
|
.hljs-addition,
|
||||||
|
.hljs-title.class_.inherited__,
|
||||||
|
.hljs-string {
|
||||||
|
color: #7d9726;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0C - Support, Regular Expressions, Escape Characters, Markup Quotes */
|
||||||
|
.hljs-built_in,
|
||||||
|
.hljs-doctag, /* guessing */
|
||||||
|
.hljs-quote,
|
||||||
|
.hljs-keyword.hljs-atrule,
|
||||||
|
.hljs-regexp {
|
||||||
|
color: #5b9d48;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0D - Functions, Methods, Attribute IDs, Headings */
|
||||||
|
.hljs-function .hljs-title,
|
||||||
|
.hljs-attribute,
|
||||||
|
.ruby .hljs-property,
|
||||||
|
.hljs-title.function_,
|
||||||
|
.hljs-section {
|
||||||
|
color: #36a166;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed */
|
||||||
|
.hljs-type,
|
||||||
|
.hljs-template-tag,
|
||||||
|
.diff .hljs-meta,
|
||||||
|
.hljs-keyword {
|
||||||
|
color: #5f9182;
|
||||||
|
}
|
||||||
|
.hljs-emphasis {
|
||||||
|
color: #5f9182;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. <?php ?> */
|
||||||
|
.hljs-meta,
|
||||||
|
.hljs-meta .hljs-keyword,
|
||||||
|
.hljs-meta .hljs-string {
|
||||||
|
color: #9d6c7c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-meta .hljs-keyword,
|
||||||
|
.hljs-meta-keyword {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.headerInfo {
|
||||||
|
@apply text-sm text-gray-500 pl-2;
|
||||||
|
:global(.dark) & {
|
||||||
|
@apply text-gray-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
address, time {
|
||||||
|
@apply inline not-italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.articleEnd {
|
||||||
|
@apply text-center text-gray-400 text-sm my-6;
|
||||||
|
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: "※";
|
||||||
|
@apply mx-4 text-xs align-text-top;
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
.loginWrapper {
|
|
||||||
@apply flex sm:items-center justify-center flex-col w-screen px-4 sm:px-0 items-stretch bg-green-50;
|
|
||||||
}
|
|
||||||
.login {
|
|
||||||
}
|
|
||||||
|
|
||||||
.form {
|
|
||||||
@apply w-full md:w-96 py-4 px-8 shadow-md rounded-lg;
|
|
||||||
@apply bg-white;
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import styles from "./login.module.css";
|
|
||||||
import { Field, Form, Formik, FormikHelpers } from "formik";
|
|
||||||
import * as yup from "yup";
|
|
||||||
import { TextField } from "formik-material-ui";
|
|
||||||
import { Button, InputAdornment, makeStyles } from "@material-ui/core";
|
|
||||||
import classNames from "classnames";
|
|
||||||
import { AccountCircle, Lock } from "@material-ui/icons";
|
|
||||||
import { LoggedInfo, LoginInput } from "../../commons/graphql/generated";
|
|
||||||
import { useMutation } from "@apollo/client";
|
|
||||||
import { LOGIN } from "./mutations";
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
field: {
|
|
||||||
margin: "16px 0",
|
|
||||||
},
|
|
||||||
loginBtn: {
|
|
||||||
margin: "8px 0",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default function Index() {
|
|
||||||
const [messagePort, setMessagePort] = useState(() => undefined);
|
|
||||||
useEffect(() => {
|
|
||||||
const { port1, port2 } = new MessageChannel();
|
|
||||||
setMessagePort(port1);
|
|
||||||
port1.onmessage = (ev: MessageEvent) => {
|
|
||||||
console.log(ev);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.opener?.postMessage("init-channel", "*", [port2]);
|
|
||||||
window.parent?.postMessage("init-channel", "*", [port2]);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const [login, { loading: logining }] =
|
|
||||||
useMutation<{ login: LoggedInfo }>(LOGIN);
|
|
||||||
const submit = (values, helpers: FormikHelpers<LoggedInfo>) => {
|
|
||||||
login({
|
|
||||||
variables: {
|
|
||||||
input: values,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(({ data }) => {
|
|
||||||
messagePort.postMessage({
|
|
||||||
type: "logged",
|
|
||||||
payload: data.login,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
helpers.setSubmitting(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const classes = useStyles();
|
|
||||||
return (
|
|
||||||
<div className={styles.loginWrapper}>
|
|
||||||
<main className={styles.login}>
|
|
||||||
<Formik
|
|
||||||
initialValues={
|
|
||||||
{
|
|
||||||
name: "",
|
|
||||||
password: "",
|
|
||||||
} as LoginInput
|
|
||||||
}
|
|
||||||
validationSchema={yup.object().shape({
|
|
||||||
name: yup.string().max(100, "怎么会有这么长的用户名!!"),
|
|
||||||
password: yup
|
|
||||||
.string()
|
|
||||||
.max(100, "不会吧不会吧,怎么会有这么长的密码?"),
|
|
||||||
})}
|
|
||||||
onSubmit={submit}
|
|
||||||
>
|
|
||||||
{({ isSubmitting }) => {
|
|
||||||
return (
|
|
||||||
<Form className={styles.form}>
|
|
||||||
<Field
|
|
||||||
className={classNames(classes.field)}
|
|
||||||
name="name"
|
|
||||||
component={TextField}
|
|
||||||
placeholder="账户 / Username"
|
|
||||||
size="medium"
|
|
||||||
fullWidth
|
|
||||||
InputProps={{
|
|
||||||
startAdornment: (
|
|
||||||
<InputAdornment position="start">
|
|
||||||
<AccountCircle />
|
|
||||||
</InputAdornment>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Field
|
|
||||||
className={classNames(classes.field)}
|
|
||||||
name="password"
|
|
||||||
component={TextField}
|
|
||||||
placeholder="密码 / Password"
|
|
||||||
size="medium"
|
|
||||||
type="password"
|
|
||||||
fullWidth
|
|
||||||
InputProps={{
|
|
||||||
startAdornment: (
|
|
||||||
<InputAdornment position="start">
|
|
||||||
<Lock />
|
|
||||||
</InputAdornment>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
fullWidth
|
|
||||||
type="submit"
|
|
||||||
className={classes.loginBtn}
|
|
||||||
disabled={isSubmitting}
|
|
||||||
>
|
|
||||||
登录 / Login
|
|
||||||
</Button>
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Formik>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
import { gql } from "@apollo/client";
|
|
||||||
export const LOGIN = gql`
|
|
||||||
mutation Login($input: LoginInput!) {
|
|
||||||
login(loginInput: $input) {
|
|
||||||
account {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
nick
|
|
||||||
}
|
|
||||||
accessToken
|
|
||||||
refreshToken
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
@ -2,13 +2,45 @@ import { useQuery } from "@apollo/client";
|
|||||||
import { GetServerSideProps } from 'next';
|
import { GetServerSideProps } from 'next';
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { addApolloState, initializeApollo } from '../commons/graphql/client';
|
||||||
|
import { Article } from "../commons/graphql/generated";
|
||||||
|
import { ARTICLE_FOR_HOME } from "../commons/graphql/queries";
|
||||||
|
import styles from "./index.module.css";
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
|
const { data, loading } = useQuery<{ articles: Article[] }>(ARTICLE_FOR_HOME);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main>
|
<main className={styles.index}>
|
||||||
<h1>Launch</h1>
|
<ol>
|
||||||
<hr />
|
{data?.articles?.map((article) => (
|
||||||
<p>Powered By Ivan.</p>
|
<Item article={article} key={article.id} />
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Item({ article }: { article: Article }) {
|
||||||
|
return (
|
||||||
|
<Link href={`/articles/${article.id}`}>
|
||||||
|
<li className={styles.item}>
|
||||||
|
<h2 className={styles.title}>{article.title}</h2>
|
||||||
|
<p className={styles.description}>{article.description}</p>
|
||||||
|
</li>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
|
||||||
|
const apolloClient = initializeApollo();
|
||||||
|
|
||||||
|
await apolloClient.query({
|
||||||
|
query: ARTICLE_FOR_HOME,
|
||||||
|
});
|
||||||
|
|
||||||
|
return addApolloState(apolloClient, {
|
||||||
|
props: {},
|
||||||
|
});
|
||||||
};
|
};
|
@ -1,5 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
mode: "jit",
|
|
||||||
purge: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
|
purge: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
|
||||||
darkMode: "class", // or 'media' or 'class'
|
darkMode: "class", // or 'media' or 'class'
|
||||||
theme: {
|
theme: {
|
||||||
|
Loading…
Reference in New Issue
Block a user