zrb 0.0.52__py3-none-any.whl → 0.0.53__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zrb/builtin/generator/fastapp/template/_automate/snake_app_name/cmd/start.sh +1 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/.gitignore +1 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/config.py +14 -5
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/.env.local +4 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/.gitignore +1 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/README.md +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/package-lock.json +16 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/package.json +2 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/playwright.config.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/postcss.config.js +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/app.css +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/app.d.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/app.html +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/index.test.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/helper.ts +146 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/store.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/type.ts +3 -3
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/Menu.svelte +19 -16
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/Navigation.svelte +14 -11
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/helper.ts +18 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/type.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/config/app.ts +9 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/config/navData.ts +6 -17
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/error/helper.ts +12 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+error.svelte +8 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+layout.js +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+layout.svelte +4 -3
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+page.svelte +2 -8
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/static/favicon.png +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/static/logo.png +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/svelte.config.js +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/tailwind.config.js +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/tests/test.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/tsconfig.json +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/vite.config.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/__init__.py +8 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/access_token_scheme.py +14 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/access_token_util.py +17 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/bearer_token_scheme.py +5 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/model/user_model.py +9 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/refresh_token_util.py +17 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/__init__.py +14 -9
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_scheme/oauth2_bearer_token_scheme.py → access_token/scheme.py} +11 -11
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/access_token/util.py +69 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/authorizer/rpc_authorizer.py +4 -2
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_util/jwt_token_util.py → refresh_token/util.py} +18 -6
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/group/api.py +9 -7
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/group/rpc.py +4 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/permission/api.py +9 -7
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/permission/rpc.py +4 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/api.py +25 -15
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/model.py +44 -19
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/rpc.py +19 -11
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/schema/request.py +2 -2
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/schema/token.py +7 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/requirements.txt +1 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/template.env +7 -3
- zrb/builtin/generator/fastapp_crud/add.py +7 -21
- zrb/builtin/generator/fastapp_crud/add_navigation.py +32 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/+page.svelte +121 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/delete/[id]/+page.svelte +75 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/delete/[id]/+page.ts +5 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/detail/[id]/+page.svelte +54 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/detail/[id]/+page.ts +5 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/new/+page.svelte +52 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/update/[id]/+page.svelte +78 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/update/[id]/+page.ts +5 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/module/snake_module_name/entity/snake_entity_name/api.py +9 -7
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/module/snake_module_name/entity/snake_entity_name/rpc.py +4 -4
- zrb/builtin/generator/fastapp_field/add.py +203 -4
- zrb/builtin/generator/project/template/.gitignore +1 -1
- zrb/builtin/generator/simple_python_app/template/src/kebab-app-name/src/.gitignore +1 -1
- zrb/helper/util.py +4 -0
- zrb/task/resource_maker.py +2 -1
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/METADATA +3 -3
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/RECORD +64 -56
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/auth.ts +0 -83
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/config/config.ts +0 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/cookie/cookie.ts +0 -19
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/about/+page.svelte +0 -2
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/greetings/[slug]/+page.js +0 -6
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/greetings/[slug]/+page.svelte +0 -5
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/sample/+page.svelte +0 -37
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/sample/delete/[id]/+page.svelte +0 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/token_scheme.py +0 -11
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/token_util.py +0 -17
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/token_scheme/token_sheme.py +0 -5
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/token_util/token_util.py +0 -13
- /zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_scheme/__init__.py → access_token/_init_.py} +0 -0
- /zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_util/__init__.py → refresh_token/_init_.py} +0 -0
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/LICENSE +0 -0
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/WHEEL +0 -0
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/entry_points.txt +0 -0
zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/rpc.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
from typing import Any, Mapping
|
1
|
+
from typing import Any, Mapping, List, Union
|
2
2
|
from logging import Logger
|
3
3
|
from core.messagebus import Publisher
|
4
4
|
from core.rpc import Caller, Server
|
5
5
|
from core.repo import SearchFilter
|
6
6
|
from module.auth.component.model.user_model import user_model
|
7
7
|
from module.auth.schema.user import UserData, UserLogin
|
8
|
-
from module.auth.schema.token import
|
8
|
+
from module.auth.schema.token import AccessTokenData
|
9
9
|
|
10
10
|
|
11
11
|
def register_rpc(
|
@@ -32,20 +32,28 @@ def register_rpc(
|
|
32
32
|
|
33
33
|
@rpc_server.register('auth_is_user_authorized')
|
34
34
|
async def is_user_having_permission(
|
35
|
-
id: str,
|
35
|
+
id: str, permission_name: Union[str, List[str]]
|
36
36
|
) -> Mapping[str, bool]:
|
37
37
|
'''
|
38
38
|
Used by RPC Authenticator
|
39
39
|
'''
|
40
|
-
|
40
|
+
if isinstance(permission_name, str):
|
41
|
+
return await user_model.is_authorized(id, permission_name)
|
42
|
+
return await user_model.is_authorized(id, *permission_name)
|
41
43
|
|
42
44
|
@rpc_server.register('auth_create_token')
|
43
|
-
async def create_token(login_data: Mapping[str, str]) -> str:
|
44
|
-
|
45
|
+
async def create_token(login_data: Mapping[str, str]) -> Mapping[str, str]:
|
46
|
+
result = await user_model.create_auth_token(UserLogin(**login_data))
|
47
|
+
return result.dict()
|
45
48
|
|
46
49
|
@rpc_server.register('auth_refresh_token')
|
47
|
-
async def refresh_token(
|
48
|
-
|
50
|
+
async def refresh_token(
|
51
|
+
refresh_token: str, access_token: str
|
52
|
+
) -> Mapping[str, str]:
|
53
|
+
result = await user_model.refresh_auth_token(
|
54
|
+
refresh_token, access_token
|
55
|
+
)
|
56
|
+
return result.dict()
|
49
57
|
|
50
58
|
@rpc_server.register('auth_get_user')
|
51
59
|
async def get(
|
@@ -77,7 +85,7 @@ def register_rpc(
|
|
77
85
|
data: Mapping[str, Any],
|
78
86
|
user_token_data: Mapping[str, Any]
|
79
87
|
) -> Mapping[str, Any]:
|
80
|
-
user_token_data =
|
88
|
+
user_token_data = AccessTokenData(**user_token_data)
|
81
89
|
data['created_by'] = user_token_data.user_id
|
82
90
|
data['updated_by'] = user_token_data.user_id
|
83
91
|
row = await user_model.insert(
|
@@ -91,7 +99,7 @@ def register_rpc(
|
|
91
99
|
data: Mapping[str, Any],
|
92
100
|
user_token_data: Mapping[str, Any]
|
93
101
|
) -> Mapping[str, Any]:
|
94
|
-
user_token_data =
|
102
|
+
user_token_data = AccessTokenData(**user_token_data)
|
95
103
|
data['updated_by'] = user_token_data.user_id
|
96
104
|
row = await user_model.update(
|
97
105
|
id=id, data=UserData(**data)
|
@@ -103,6 +111,6 @@ def register_rpc(
|
|
103
111
|
id: str,
|
104
112
|
user_token_data: Mapping[str, Any]
|
105
113
|
) -> Mapping[str, Any]:
|
106
|
-
user_token_data =
|
114
|
+
user_token_data = AccessTokenData(**user_token_data)
|
107
115
|
row = await user_model.delete(id=id)
|
108
116
|
return row.dict()
|
@@ -1,12 +1,18 @@
|
|
1
1
|
from pydantic import BaseModel
|
2
2
|
|
3
3
|
|
4
|
-
class
|
4
|
+
class AccessTokenData(BaseModel):
|
5
5
|
user_id: str
|
6
6
|
username: str
|
7
7
|
expire_seconds: int
|
8
8
|
|
9
9
|
|
10
|
+
class RefreshTokenData(BaseModel):
|
11
|
+
user_id: str
|
12
|
+
expire_seconds: int
|
13
|
+
|
14
|
+
|
10
15
|
class TokenResponse(BaseModel):
|
11
16
|
access_token: str
|
17
|
+
refresh_token: str
|
12
18
|
token_type: str
|
@@ -7,10 +7,14 @@ APP_MAX_NOT_READY=10
|
|
7
7
|
|
8
8
|
PUBLIC_BRAND=PascalAppName
|
9
9
|
PUBLIC_TITLE=PascalAppName
|
10
|
-
|
10
|
+
PUBLIC_AUTH_ACCESS_TOKEN_COOKIE_KEY=access_token
|
11
|
+
PUBLIC_AUTH_REFRESH_TOKEN_COOKIE_KEY=refresh_token
|
12
|
+
|
13
|
+
APP_AUTH_ACCESS_TOKEN_EXPIRE_SECONDS=300
|
14
|
+
APP_AUTH_ACCESS_TOKEN_TYPE=jwt
|
15
|
+
APP_AUTH_REFRESH_TOKEN_EXPIRE_SECONDS=21600
|
16
|
+
APP_AUTH_REFRESH_TOKEN_TYPE=jwt
|
11
17
|
|
12
|
-
APP_AUTH_TOKEN_EXPIRE_SECONDS=300
|
13
|
-
APP_AUTH_TOKEN_TYPE=jwt
|
14
18
|
APP_AUTH_JWT_TOKEN_SECRET_KEY=Alch3mist
|
15
19
|
APP_AUTH_JWT_TOKEN_ALGORITHM=HS256
|
16
20
|
|
@@ -5,15 +5,16 @@ from ....task.decorator import python_task
|
|
5
5
|
from ....task.cmd_task import CmdTask
|
6
6
|
from ....task.resource_maker import ResourceMaker
|
7
7
|
from ....runner import runner
|
8
|
+
from ....helper import util
|
9
|
+
from ....helper.codemod.add_import_module import add_import_module
|
10
|
+
from ....helper.codemod.append_code_to_function import append_code_to_function
|
11
|
+
from ....helper.file.text import read_text_file_async, write_text_file_async
|
8
12
|
from .._common.input import (
|
9
13
|
project_dir_input, app_name_input, module_name_input, entity_name_input,
|
10
14
|
plural_entity_name_input, main_column_name_input
|
11
15
|
)
|
12
16
|
from .._common.helper import validate_project_dir
|
13
|
-
from
|
14
|
-
from ....helper.codemod.add_import_module import add_import_module
|
15
|
-
from ....helper.codemod.append_code_to_function import append_code_to_function
|
16
|
-
from ....helper.file.text import read_text_file_async, write_text_file_async
|
17
|
+
from .add_navigation import create_add_navigation_task
|
17
18
|
|
18
19
|
import asyncio
|
19
20
|
import os
|
@@ -128,26 +129,11 @@ prepare_codemod = CmdTask(
|
|
128
129
|
]
|
129
130
|
)
|
130
131
|
|
131
|
-
|
132
|
-
nav_file_path = '{{input.project_dir}}/src/{{util.to_kebab_case(input.app_name)}}/src/frontend/src/lib/config/navData.ts' # noqa
|
133
|
-
var_name = 'navData'
|
134
|
-
title = '{{util.to_pascal_case(input.entity_name)}}'
|
135
|
-
url = '{{util.to_kebab_case(input.module_name)}}/{{util.to_kebab_case(input.entity_name)}}' # noqa
|
136
|
-
permission = ''
|
137
|
-
add_navigation = CmdTask(
|
138
|
-
name='add-navigation',
|
139
|
-
inputs=[
|
140
|
-
project_dir_input,
|
141
|
-
app_name_input,
|
142
|
-
module_name_input,
|
143
|
-
entity_name_input,
|
144
|
-
],
|
132
|
+
add_navigation = create_add_navigation_task(
|
145
133
|
upstreams=[
|
146
134
|
copy_resource,
|
147
135
|
prepare_codemod,
|
148
|
-
]
|
149
|
-
retry=0,
|
150
|
-
cmd=f'node {codemod_dir}/dist/addNav.js "{nav_file_path}" "{var_name}" "{title}" "{url}" "{permission}"' # noqa
|
136
|
+
]
|
151
137
|
)
|
152
138
|
|
153
139
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
from typing import List
|
2
|
+
from ....task.task import Task
|
3
|
+
from ....task.cmd_task import CmdTask
|
4
|
+
from .._common.input import (
|
5
|
+
project_dir_input, app_name_input, module_name_input, entity_name_input,
|
6
|
+
)
|
7
|
+
|
8
|
+
import os
|
9
|
+
|
10
|
+
current_dir = os.path.dirname(__file__)
|
11
|
+
codemod_dir = os.path.join(current_dir, 'nodejs', 'codemod')
|
12
|
+
|
13
|
+
nav_config_file_path = '{{input.project_dir}}/src/{{util.to_kebab_case(input.app_name)}}/src/frontend/src/lib/config/navData.ts' # noqa
|
14
|
+
nav_var_name = 'navData'
|
15
|
+
nav_title = '{{util.to_pascal_case(input.entity_name)}}'
|
16
|
+
nav_url = '/{{util.to_kebab_case(input.module_name)}}/{{util.to_kebab_case(input.entity_name)}}' # noqa
|
17
|
+
nav_permission = '{{util.to_snake_case(input.module_name)}}:{{util.to_snake_case(input.entity_name)}}:get' # noqa
|
18
|
+
|
19
|
+
|
20
|
+
def create_add_navigation_task(upstreams: List[Task]) -> Task:
|
21
|
+
return CmdTask(
|
22
|
+
name='add-navigation',
|
23
|
+
inputs=[
|
24
|
+
project_dir_input,
|
25
|
+
app_name_input,
|
26
|
+
module_name_input,
|
27
|
+
entity_name_input,
|
28
|
+
],
|
29
|
+
upstreams=upstreams,
|
30
|
+
retry=0,
|
31
|
+
cmd=f'node {codemod_dir}/dist/addNav.js "{nav_config_file_path}" "{nav_var_name}" "{nav_title}" "{nav_url}" "{nav_permission}"' # noqa
|
32
|
+
)
|
@@ -0,0 +1,121 @@
|
|
1
|
+
<script lang="ts">
|
2
|
+
import axios from 'axios';
|
3
|
+
import { onMount } from 'svelte';
|
4
|
+
import { ensureAccessToken } from '$lib/auth/helper';
|
5
|
+
import { getErrorMessage } from '$lib/error/helper';
|
6
|
+
|
7
|
+
let limit: number = 5;
|
8
|
+
let pageIndex: number = 0;
|
9
|
+
let count: number = 0;
|
10
|
+
let keyword: string = '';
|
11
|
+
let isAlertVisible: boolean = false;
|
12
|
+
let errorMessage: string = '';
|
13
|
+
|
14
|
+
let limitOptions: Array<number> = [5, 10, 30, 50, 100];
|
15
|
+
let pageIndexes: Array<number> = [];
|
16
|
+
let rows: Array<any> = [];
|
17
|
+
|
18
|
+
onMount(async() => {
|
19
|
+
await loadRows();
|
20
|
+
});
|
21
|
+
|
22
|
+
async function loadRows() {
|
23
|
+
const accessToken = await ensureAccessToken();
|
24
|
+
try {
|
25
|
+
const encodedKeyword = encodeURIComponent(keyword);
|
26
|
+
const offset = limit * pageIndex
|
27
|
+
const response = await axios.get(
|
28
|
+
`/api/v1/kebab-module-name/kebab-plural-entity-name?limit=${limit}&offset=${offset}&keyword=${encodedKeyword}`,
|
29
|
+
{headers: {Authorization: `Bearer ${accessToken}`}}
|
30
|
+
);
|
31
|
+
if (response?.status == 200 && response?.data) {
|
32
|
+
count = response.data.count;
|
33
|
+
rows = response.data.data;
|
34
|
+
pageIndexes = [];
|
35
|
+
for (let i = 0; i*limit < count; i++) {
|
36
|
+
pageIndexes.push(i);
|
37
|
+
}
|
38
|
+
return;
|
39
|
+
}
|
40
|
+
errorMessage = 'Unknown error';
|
41
|
+
} catch(error) {
|
42
|
+
console.error(error);
|
43
|
+
errorMessage = getErrorMessage(error);
|
44
|
+
}
|
45
|
+
isAlertVisible = true;
|
46
|
+
}
|
47
|
+
|
48
|
+
async function onPaginationClick(index: number) {
|
49
|
+
pageIndex = index;
|
50
|
+
await loadRows();
|
51
|
+
}
|
52
|
+
</script>
|
53
|
+
|
54
|
+
<h1 class="text-3xl">Book</h1>
|
55
|
+
<div class="overflow-x-auto">
|
56
|
+
|
57
|
+
<div class="flex items-center mb-5 mt-5">
|
58
|
+
<label for="limit" class="mr-2">Row per page:</label>
|
59
|
+
<select id="limit" class="select select-bordered mr-2" bind:value={limit} on:change={loadRows}>
|
60
|
+
{#each limitOptions as limitOption}
|
61
|
+
{#if limitOption == limit }
|
62
|
+
<option selected>{limitOption}</option>
|
63
|
+
{:else}
|
64
|
+
<option>{limitOption}</option>
|
65
|
+
{/if}
|
66
|
+
{/each}
|
67
|
+
</select>
|
68
|
+
<input type="text" placeholder="Search..." class="input input-bordered mr-2" bind:value={keyword} />
|
69
|
+
<button class="btn btn-primary btn-square" on:click={loadRows}>
|
70
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
71
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
72
|
+
</svg>
|
73
|
+
</button>
|
74
|
+
<a class="btn ml-5" href="./new">New</a>
|
75
|
+
</div>
|
76
|
+
|
77
|
+
<div class="alert alert-error shadow-lg mt-5 mb-5 {isAlertVisible? 'visible': 'hidden'}">
|
78
|
+
<div>
|
79
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current flex-shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
80
|
+
<span>{errorMessage}</span>
|
81
|
+
</div>
|
82
|
+
</div>
|
83
|
+
|
84
|
+
<table class="table w-full">
|
85
|
+
<!-- head -->
|
86
|
+
<thead>
|
87
|
+
<tr>
|
88
|
+
<th></th>
|
89
|
+
<th>Human readable column name</th>
|
90
|
+
<!-- DON'T DELETE: insert new column header here-->
|
91
|
+
<th></th>
|
92
|
+
</tr>
|
93
|
+
</thead>
|
94
|
+
<tbody>
|
95
|
+
{#each rows as row}
|
96
|
+
<tr>
|
97
|
+
<th>{row.id}</th>
|
98
|
+
<td>{row.snake_column_name}</td>
|
99
|
+
<!-- DON'T DELETE: insert new column here-->
|
100
|
+
<td>
|
101
|
+
<a class="btn" href="./detail/{row.id}">Detail</a>
|
102
|
+
<a class="btn" href="./update/{row.id}">Update</a>
|
103
|
+
<a class="btn btn-accent" href="./delete/{row.id}">Delete</a>
|
104
|
+
</td>
|
105
|
+
</tr>
|
106
|
+
{/each}
|
107
|
+
</tbody>
|
108
|
+
</table>
|
109
|
+
|
110
|
+
<div class="btn-group justify-center w-full">
|
111
|
+
{#each pageIndexes as pageIndexOption}
|
112
|
+
{#if pageIndexOption == pageIndex}
|
113
|
+
<button class="btn btn-disabled">{pageIndexOption + 1}</button>
|
114
|
+
{:else}
|
115
|
+
<button class="btn" on:click={async () => await onPaginationClick(pageIndexOption)}>
|
116
|
+
{pageIndexOption + 1}
|
117
|
+
</button>
|
118
|
+
{/if}
|
119
|
+
{/each}
|
120
|
+
</div>
|
121
|
+
</div>
|
@@ -0,0 +1,75 @@
|
|
1
|
+
<script lang="ts">
|
2
|
+
import axios from 'axios';
|
3
|
+
import { onMount } from 'svelte';
|
4
|
+
import { goto } from '$app/navigation';
|
5
|
+
import { ensureAccessToken } from '$lib/auth/helper';
|
6
|
+
import { getErrorMessage } from '$lib/error/helper';
|
7
|
+
|
8
|
+
export let data: {id?: string} = {};
|
9
|
+
|
10
|
+
let row: any = {};
|
11
|
+
let isAlertVisible: boolean = false;
|
12
|
+
let errorMessage: string = '';
|
13
|
+
|
14
|
+
onMount(async() => {
|
15
|
+
await loadRow();
|
16
|
+
});
|
17
|
+
|
18
|
+
async function loadRow() {
|
19
|
+
const accessToken = await ensureAccessToken();
|
20
|
+
try {
|
21
|
+
const response = await axios.get(
|
22
|
+
`/api/v1/kebab-module-name/kebab-plural-entity-name/${data.id}`,
|
23
|
+
{headers: {Authorization: `Bearer ${accessToken}`}}
|
24
|
+
);
|
25
|
+
if (response?.status == 200 && response?.data) {
|
26
|
+
row = response.data;
|
27
|
+
return;
|
28
|
+
}
|
29
|
+
errorMessage = 'Unknown error';
|
30
|
+
} catch(error) {
|
31
|
+
console.error(error);
|
32
|
+
errorMessage = getErrorMessage(error);
|
33
|
+
}
|
34
|
+
isAlertVisible = true;
|
35
|
+
}
|
36
|
+
|
37
|
+
async function onDeleteClick() {
|
38
|
+
const accessToken = await ensureAccessToken();
|
39
|
+
try {
|
40
|
+
const response = await axios.delete(
|
41
|
+
`/api/v1/kebab-module-name/kebab-plural-entity-name/${data.id}`,
|
42
|
+
{headers: {Authorization: `Bearer ${accessToken}`}}
|
43
|
+
);
|
44
|
+
if (response?.status == 200 && response?.data) {
|
45
|
+
await goto('../../');
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
errorMessage = 'Unknown error';
|
49
|
+
} catch(error) {
|
50
|
+
console.error(error);
|
51
|
+
errorMessage = getErrorMessage(error);
|
52
|
+
}
|
53
|
+
isAlertVisible = true;
|
54
|
+
}
|
55
|
+
</script>
|
56
|
+
<h1 class="text-3xl">Book</h1>
|
57
|
+
|
58
|
+
<form class="max-w-md mx-auto bg-gray-100 p-6 rounded-md mt-5 mb-5">
|
59
|
+
<h2 class="text-xl font-bold mb-4">Delete Book {data.id}</h2>
|
60
|
+
<div class="mb-4">
|
61
|
+
<label class="block text-gray-700 font-bold mb-2" for="kebab-column-name">Human readable column name</label>
|
62
|
+
<span id="kebab-column-name">{row.snake_column_name}</span>
|
63
|
+
</div>
|
64
|
+
<!-- DON'T DELETE: insert new field here-->
|
65
|
+
<a href="#top" class="btn btn-accent" on:click={onDeleteClick}>Delete</a>
|
66
|
+
<a href="../../" class="btn">Cancel</a>
|
67
|
+
|
68
|
+
<div class="alert alert-error shadow-lg mt-5 {isAlertVisible? 'visible': 'hidden'}">
|
69
|
+
<div>
|
70
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current flex-shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
71
|
+
<span>{errorMessage}</span>
|
72
|
+
</div>
|
73
|
+
</div>
|
74
|
+
|
75
|
+
</form>
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<script lang="ts">
|
2
|
+
import axios from 'axios';
|
3
|
+
import { onMount } from 'svelte';
|
4
|
+
import { ensureAccessToken } from '$lib/auth/helper';
|
5
|
+
import { getErrorMessage } from '$lib/error/helper';
|
6
|
+
|
7
|
+
export let data: {id?: string} = {};
|
8
|
+
|
9
|
+
let row: any = {};
|
10
|
+
let isAlertVisible: boolean = false;
|
11
|
+
let errorMessage: string = '';
|
12
|
+
|
13
|
+
onMount(async() => {
|
14
|
+
await loadRow();
|
15
|
+
});
|
16
|
+
|
17
|
+
async function loadRow() {
|
18
|
+
const accessToken = await ensureAccessToken();
|
19
|
+
try {
|
20
|
+
const response = await axios.get(
|
21
|
+
`/api/v1/kebab-module-name/kebab-plural-entity-name/${data.id}`,
|
22
|
+
{headers: {Authorization: `Bearer ${accessToken}`}}
|
23
|
+
);
|
24
|
+
if (response?.status == 200 && response?.data) {
|
25
|
+
row = response.data;
|
26
|
+
return;
|
27
|
+
}
|
28
|
+
errorMessage = 'Unknown error';
|
29
|
+
} catch(error) {
|
30
|
+
console.error(error);
|
31
|
+
errorMessage = getErrorMessage(error);
|
32
|
+
}
|
33
|
+
isAlertVisible = true;
|
34
|
+
}
|
35
|
+
</script>
|
36
|
+
<h1 class="text-3xl">Book</h1>
|
37
|
+
|
38
|
+
<form class="max-w-md mx-auto bg-gray-100 p-6 rounded-md mt-5 mb-5">
|
39
|
+
<h2 class="text-xl font-bold mb-4">Show Book {data.id}</h2>
|
40
|
+
<div class="mb-4">
|
41
|
+
<label class="block text-gray-700 font-bold mb-2" for="kebab-column-name">Human readable column name</label>
|
42
|
+
<span id="kebab-column-name">{row.snake_column_name}</span>
|
43
|
+
</div>
|
44
|
+
<!-- DON'T DELETE: insert new field here-->
|
45
|
+
<a href="../../" class="btn btn-primary">Show others</a>
|
46
|
+
|
47
|
+
<div class="alert alert-error shadow-lg mt-5 {isAlertVisible? 'visible': 'hidden'}">
|
48
|
+
<div>
|
49
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current flex-shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
50
|
+
<span>{errorMessage}</span>
|
51
|
+
</div>
|
52
|
+
</div>
|
53
|
+
|
54
|
+
</form>
|
@@ -0,0 +1,52 @@
|
|
1
|
+
<script lang="ts">
|
2
|
+
import axios from 'axios';
|
3
|
+
import { goto } from '$app/navigation';
|
4
|
+
import { ensureAccessToken } from '$lib/auth/helper';
|
5
|
+
import { getErrorMessage } from '$lib/error/helper';
|
6
|
+
|
7
|
+
let row: any = {}
|
8
|
+
let isAlertVisible: boolean = false;
|
9
|
+
let isSaving: boolean = false;
|
10
|
+
let errorMessage: string = '';
|
11
|
+
|
12
|
+
async function onSaveClick() {
|
13
|
+
isSaving = true
|
14
|
+
const accessToken = await ensureAccessToken();
|
15
|
+
try {
|
16
|
+
const response = await axios.post(
|
17
|
+
'/api/v1/kebab-module-name/kebab-plural-entity-name', row, {headers: {Authorization: `Bearer ${accessToken}`}}
|
18
|
+
);
|
19
|
+
if (response?.status == 200) {
|
20
|
+
await goto('../');
|
21
|
+
return;
|
22
|
+
}
|
23
|
+
errorMessage = 'Unknown error';
|
24
|
+
} catch(error) {
|
25
|
+
console.error(error);
|
26
|
+
errorMessage = getErrorMessage(error);
|
27
|
+
}
|
28
|
+
isAlertVisible = true;
|
29
|
+
isSaving = false;
|
30
|
+
}
|
31
|
+
</script>
|
32
|
+
|
33
|
+
<h1 class="text-3xl">Book</h1>
|
34
|
+
|
35
|
+
<form class="max-w-md mx-auto bg-gray-100 p-6 rounded-md mt-5 mb-5">
|
36
|
+
<h2 class="text-xl font-bold mb-4">New Book</h2>
|
37
|
+
<div class="mb-4">
|
38
|
+
<label class="block text-gray-700 font-bold mb-2" for="kebab-column-name">Human readable column name</label>
|
39
|
+
<input type="text" class="input w-full" id="kebab-column-name" placeholder="Human readable column name" bind:value={row.snake_column_name}>
|
40
|
+
</div>
|
41
|
+
<!-- DON'T DELETE: insert new field here-->
|
42
|
+
<a href="#top" class="btn btn-primary {isSaving ? 'btn-disabled': '' }" on:click={onSaveClick}>Save</a>
|
43
|
+
<a href="../" class="btn">Cancel</a>
|
44
|
+
|
45
|
+
<div class="alert alert-error shadow-lg mt-5 {isAlertVisible? 'visible': 'hidden'}">
|
46
|
+
<div>
|
47
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current flex-shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
48
|
+
<span>{errorMessage}</span>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
|
52
|
+
</form>
|
@@ -0,0 +1,78 @@
|
|
1
|
+
<script lang="ts">
|
2
|
+
import axios from 'axios';
|
3
|
+
import { onMount } from 'svelte';
|
4
|
+
import { goto } from '$app/navigation';
|
5
|
+
import { ensureAccessToken } from '$lib/auth/helper';
|
6
|
+
import { getErrorMessage } from '$lib/error/helper';
|
7
|
+
|
8
|
+
export let data: {id?: string} = {};
|
9
|
+
|
10
|
+
let row: any = {}
|
11
|
+
let isAlertVisible: boolean = false;
|
12
|
+
let isSaving: boolean = false;
|
13
|
+
let errorMessage: string = '';
|
14
|
+
|
15
|
+
onMount(async() => {
|
16
|
+
await loadRow();
|
17
|
+
});
|
18
|
+
|
19
|
+
async function loadRow() {
|
20
|
+
const accessToken = await ensureAccessToken();
|
21
|
+
try {
|
22
|
+
const response = await axios.get(
|
23
|
+
`/api/v1/kebab-module-name/kebab-plural-entity-name/${data.id}`,
|
24
|
+
{headers: {Authorization: `Bearer ${accessToken}`}}
|
25
|
+
);
|
26
|
+
if (response?.status == 200 && response?.data) {
|
27
|
+
row = response.data;
|
28
|
+
return;
|
29
|
+
}
|
30
|
+
errorMessage = 'Unknown error';
|
31
|
+
} catch(error) {
|
32
|
+
console.error(error);
|
33
|
+
errorMessage = getErrorMessage(error);
|
34
|
+
}
|
35
|
+
isAlertVisible = true;
|
36
|
+
}
|
37
|
+
|
38
|
+
async function onSaveClick() {
|
39
|
+
isSaving = true
|
40
|
+
const accessToken = await ensureAccessToken();
|
41
|
+
try {
|
42
|
+
const response = await axios.put(
|
43
|
+
`/api/v1/kebab-module-name/kebab-plural-entity-name/${data.id}`, row, {headers: {Authorization: `Bearer ${accessToken}`}}
|
44
|
+
);
|
45
|
+
if (response?.status == 200) {
|
46
|
+
await goto('../../');
|
47
|
+
return;
|
48
|
+
}
|
49
|
+
errorMessage = 'Unknown error';
|
50
|
+
} catch(error) {
|
51
|
+
console.error(error);
|
52
|
+
errorMessage = getErrorMessage(error);
|
53
|
+
}
|
54
|
+
isAlertVisible = true;
|
55
|
+
isSaving = false;
|
56
|
+
}
|
57
|
+
</script>
|
58
|
+
|
59
|
+
<h1 class="text-3xl">Book</h1>
|
60
|
+
|
61
|
+
<form class="max-w-md mx-auto bg-gray-100 p-6 rounded-md mt-5 mb-5">
|
62
|
+
<h2 class="text-xl font-bold mb-4">Update Book</h2>
|
63
|
+
<div class="mb-4">
|
64
|
+
<label class="block text-gray-700 font-bold mb-2" for="kebab-column-name">Human readable column name</label>
|
65
|
+
<input type="text" class="input w-full" id="kebab-column-name" placeholder="Human readable column name" bind:value={row.snake_column_name}>
|
66
|
+
</div>
|
67
|
+
<!-- DON'T DELETE: insert new field here-->
|
68
|
+
<a href="#top" class="btn btn-primary {isSaving ? 'btn-disabled': '' }" on:click={onSaveClick}>Save</a>
|
69
|
+
<a href="../../" class="btn">Cancel</a>
|
70
|
+
|
71
|
+
<div class="alert alert-error shadow-lg mt-5 {isAlertVisible? 'visible': 'hidden'}">
|
72
|
+
<div>
|
73
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current flex-shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
74
|
+
<span>{errorMessage}</span>
|
75
|
+
</div>
|
76
|
+
</div>
|
77
|
+
|
78
|
+
</form>
|