mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
integrate todolist with api
This commit is contained in:
parent
7b6555dc59
commit
a5b22a8ac1
@ -9,31 +9,34 @@
|
||||
<div id="root"></div>
|
||||
<script type="module">
|
||||
import renderApp from '../../src/main.tsx';
|
||||
const listdata = [
|
||||
|
||||
const refresh = [
|
||||
{
|
||||
id: 1,
|
||||
name: '马云',
|
||||
email: 'jack.ma@deck.com',
|
||||
componentId: 'nameInput',
|
||||
method: {
|
||||
name: 'setInputValue',
|
||||
parameters: {
|
||||
value: ``,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '马化腾',
|
||||
email: 'pony.ma@conversation.com',
|
||||
componentId: 'emailInput',
|
||||
method: {
|
||||
name: 'setInputValue',
|
||||
parameters: {
|
||||
value: ``,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '李彦宏',
|
||||
email: 'robin.li@response.com',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '张一鸣',
|
||||
email: 'yiming.zhang@example.com',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '王兴',
|
||||
email: 'xing.wang@widget.org',
|
||||
componentId: 'root',
|
||||
method: {
|
||||
name: 'triggerFetch',
|
||||
parameters: 'getCustomersQuery',
|
||||
},
|
||||
wait: {},
|
||||
disabled: 'false',
|
||||
},
|
||||
];
|
||||
|
||||
@ -61,7 +64,16 @@
|
||||
type: 'core/v1/arrayState',
|
||||
properties: {
|
||||
key: 'listData',
|
||||
initialValue: listdata,
|
||||
initialValue: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'core/v1/fetch',
|
||||
properties: {
|
||||
name: 'getCustomersQuery',
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/customers',
|
||||
method: 'get',
|
||||
headers: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -91,7 +103,8 @@
|
||||
id: 'list',
|
||||
type: 'chakra_ui/v1/list',
|
||||
properties: {
|
||||
listData: '{{ root.listData }}',
|
||||
listData:
|
||||
'{{ root.getCustomersQuery ? root.getCustomersQuery.data : [] }}',
|
||||
template: [
|
||||
{
|
||||
id: 'listItemTemplate-{{$listItem.id}}',
|
||||
@ -222,6 +235,16 @@
|
||||
},
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/fetch',
|
||||
properties: {
|
||||
name: 'deleteUserQuery',
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/customers/{{ $listItem.id }}',
|
||||
method: 'delete',
|
||||
lazy: true,
|
||||
onComplete: refresh,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'core/v1/event',
|
||||
parsedType: {
|
||||
@ -232,14 +255,10 @@
|
||||
events: [
|
||||
{
|
||||
event: 'click',
|
||||
componentId: 'root',
|
||||
componentId: 'listItemDelete-{{$listItem.id}}',
|
||||
method: {
|
||||
name: 'deleteItemById',
|
||||
parameters: {
|
||||
key: 'listData',
|
||||
itemIdKey: 'id',
|
||||
itemId: '{{ $listItem.id }}',
|
||||
},
|
||||
name: 'triggerFetch',
|
||||
parameters: 'deleteUserQuery',
|
||||
},
|
||||
wait: {},
|
||||
disabled: 'false',
|
||||
@ -324,6 +343,23 @@
|
||||
},
|
||||
},
|
||||
traits: [
|
||||
{
|
||||
type: 'core/v1/fetch',
|
||||
properties: {
|
||||
name: 'createUserQuery',
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/customers',
|
||||
method: 'post',
|
||||
headers: [
|
||||
{ key: 'Content-Type', value: 'application/json' },
|
||||
],
|
||||
body: {
|
||||
name: '{{ nameInput.value }}',
|
||||
email: '{{ emailInput.value }}',
|
||||
},
|
||||
lazy: true,
|
||||
onComplete: refresh,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'core/v1/event',
|
||||
parsedType: {
|
||||
@ -334,22 +370,10 @@
|
||||
events: [
|
||||
{
|
||||
event: 'click',
|
||||
componentId: 'root',
|
||||
componentId: 'addButton',
|
||||
method: {
|
||||
name: 'setValue',
|
||||
parameters: {
|
||||
key: 'listData',
|
||||
value: `{{
|
||||
(function() {
|
||||
let list = root.listData || []
|
||||
return list.concat({
|
||||
id: Date.now(),
|
||||
name: nameInput.value,
|
||||
email: emailInput.value
|
||||
})
|
||||
})()
|
||||
}}`,
|
||||
},
|
||||
name: 'triggerFetch',
|
||||
parameters: 'createUserQuery',
|
||||
},
|
||||
wait: {},
|
||||
disabled: 'false',
|
||||
@ -385,6 +409,35 @@
|
||||
initialValue: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'core/v1/fetch',
|
||||
properties: {
|
||||
name: 'updateUserQuery',
|
||||
url: 'https://61373521eac1410017c18209.mockapi.io/customers/{{saveButton.editingId}}',
|
||||
method: 'put',
|
||||
headers: [
|
||||
{ key: 'Content-Type', value: 'application/json' },
|
||||
],
|
||||
body: {
|
||||
name: '{{ nameInput.value }}',
|
||||
email: '{{ emailInput.value }}',
|
||||
},
|
||||
lazy: true,
|
||||
onComplete: [
|
||||
...refresh,
|
||||
{
|
||||
componentId: 'saveButton',
|
||||
method: {
|
||||
name: 'setValue',
|
||||
parameters: {
|
||||
key: 'editingId',
|
||||
value: '-1',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'core/v1/event',
|
||||
parsedType: {
|
||||
@ -393,63 +446,12 @@
|
||||
},
|
||||
properties: {
|
||||
events: [
|
||||
{
|
||||
event: 'click',
|
||||
componentId: 'root',
|
||||
method: {
|
||||
name: 'setValue',
|
||||
parameters: {
|
||||
key: 'listData',
|
||||
value: `{{
|
||||
(function() {
|
||||
const list = [...root.listData || []]
|
||||
let index = list.findIndex((item) => item.id == saveButton.editingId)
|
||||
list[index] = {
|
||||
...list[index],
|
||||
name: nameInput.value,
|
||||
email: emailInput.value
|
||||
}
|
||||
return list
|
||||
})()
|
||||
}}`,
|
||||
},
|
||||
},
|
||||
wait: {},
|
||||
disabled: 'false',
|
||||
},
|
||||
{
|
||||
event: 'click',
|
||||
componentId: 'saveButton',
|
||||
method: {
|
||||
name: 'setValue',
|
||||
parameters: {
|
||||
key: 'editingId',
|
||||
value: '-1',
|
||||
},
|
||||
},
|
||||
wait: {},
|
||||
disabled: 'false',
|
||||
},
|
||||
{
|
||||
event: 'click',
|
||||
componentId: 'nameInput',
|
||||
method: {
|
||||
name: 'setInputValue',
|
||||
parameters: {
|
||||
value: ``,
|
||||
},
|
||||
},
|
||||
wait: {},
|
||||
disabled: 'false',
|
||||
},
|
||||
{
|
||||
event: 'click',
|
||||
componentId: 'emailInput',
|
||||
method: {
|
||||
name: 'setInputValue',
|
||||
parameters: {
|
||||
value: ``,
|
||||
},
|
||||
name: 'triggerFetch',
|
||||
parameters: 'updateUserQuery',
|
||||
},
|
||||
wait: {},
|
||||
disabled: 'false',
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { createTrait } from '@meta-ui/core';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { globalHandlerMap } from '../../handler';
|
||||
import { TraitImplementation } from '../../registry';
|
||||
import { stateStore } from '../../store';
|
||||
|
||||
let hasFetched = false;
|
||||
let hasFetchedMap = new Map<string, boolean>();
|
||||
|
||||
const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
|
||||
name,
|
||||
@ -15,7 +16,9 @@ const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
|
||||
mergeState,
|
||||
subscribeMethods,
|
||||
componentId,
|
||||
onComplete,
|
||||
}) => {
|
||||
// initial data
|
||||
if (!stateStore[componentId][name]) {
|
||||
mergeState({
|
||||
[name]: {
|
||||
@ -25,19 +28,13 @@ const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const hashId = `#${componentId}@${name}`;
|
||||
const hasFetched = hasFetchedMap.get(hashId);
|
||||
const lazy = undefined ? method.toLowerCase() !== 'get' : _lazy;
|
||||
|
||||
const fetchData = () => {
|
||||
hasFetched = true;
|
||||
// before fetching, initial data
|
||||
mergeState({
|
||||
[name]: {
|
||||
loading: true,
|
||||
data: undefined,
|
||||
error: undefined,
|
||||
},
|
||||
});
|
||||
// TODO: clear when component destory
|
||||
hasFetchedMap.set(hashId, true);
|
||||
// FIXME: listen to the header change
|
||||
const headers = new Headers();
|
||||
if (_headers) {
|
||||
@ -46,11 +43,12 @@ const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
|
||||
headers.append(header.key, _headers[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
// fetch data
|
||||
fetch(url, {
|
||||
method,
|
||||
headers,
|
||||
body,
|
||||
body: JSON.stringify(body),
|
||||
}).then(
|
||||
async response => {
|
||||
if (response.ok) {
|
||||
@ -63,6 +61,12 @@ const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
|
||||
error: undefined,
|
||||
},
|
||||
});
|
||||
onComplete?.forEach(event => {
|
||||
const hanlderMap = globalHandlerMap.get(event.componentId);
|
||||
if (hanlderMap) {
|
||||
hanlderMap[event.method.name](event.method.parameters);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// TODO: Add FetchError class and remove console info
|
||||
const error = new Error(
|
||||
@ -96,16 +100,13 @@ const useFetchTrait: TraitImplementation<FetchPropertySchema> = ({
|
||||
fetchData();
|
||||
}
|
||||
|
||||
// only subscribe non lazy fetch trait
|
||||
if (lazy) {
|
||||
subscribeMethods({
|
||||
triggerFetch(key) {
|
||||
if (key === name) {
|
||||
fetchData();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
subscribeMethods({
|
||||
triggerFetch(key) {
|
||||
if (key === name) {
|
||||
fetchData();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
props: null,
|
||||
@ -120,6 +121,15 @@ const HeaderPropertySchema = Type.Array(
|
||||
Type.Object({ key: Type.String(), value: Type.String() })
|
||||
);
|
||||
const BodyPropertySchema = Type.Any(); // Type.String()?
|
||||
const OnCompletePropertySchema = Type.Array(
|
||||
Type.Object({
|
||||
componentId: Type.String(),
|
||||
method: Type.Object({
|
||||
name: Type.String(),
|
||||
parameters: Type.Any(),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
type FetchPropertySchema = {
|
||||
name: Static<typeof NamePropertySchema>;
|
||||
@ -128,6 +138,7 @@ type FetchPropertySchema = {
|
||||
lazy?: Static<typeof LazyPropertySchema>;
|
||||
headers?: Static<typeof HeaderPropertySchema>;
|
||||
body?: Static<typeof BodyPropertySchema>;
|
||||
onComplete?: Static<typeof OnCompletePropertySchema>;
|
||||
};
|
||||
|
||||
export default {
|
||||
|
Loading…
Reference in New Issue
Block a user