In this chapter, you will learn most of what you need to know about the front-end page of DEC App and be able to publish the DEC App with the front-end page to OOD. Combined with the Dec_Service content you have learned before, you will be able to form a complete Dec App.
Front-end code is fully stored on OOD at install time and must match the corresponding back-end. cyfs-sdk fully supports typescript, providing web developers with a cloud-integrated development experience: using typescript can basically complete the development of DEC App.
a link
is a link used to deal with the application page of the DEC App. The front-end page is the main form of the application page.
The url basic paradigm of a link
is as follows:
cyfs://a/$decid[/$dirid]/$inner_path[?parms]
The dirid in a link
can be used to specify the object-id (dir-id or objectmap-id) of a specific version of the built-in page. If no dirid is specified, the current version is used, or the app's semantic version x.x.x.
a link
currently supports the following 3 modes:
-
cyfs://a/{dec-id}/{inner-path}
-
cyfs://a/{dec-id}/{dir-id}/{inner-path}
-
cyfs://a/{dec-id}/{x.x.x}/{inner-path}
- See src/www/initialize.ts for complete code
Front-end initialization mainly completes 3 steps:
- Select the OOD environment (REAL) or a specific Zone (FIRST or SECOND) in the simulator environment
- MetaClient initialization, select beta
- Open and wait for runtime-stack to go online
code show as below:
export async function init() {
useSimulator(SimulatorZoneNo.REAL, SimulatorDeviceNo.FIRST);
MetaClient.init(MetaClient.EnvTarget.BETA);
await waitStackRuntime(DEC_ID);
}
- page components see src/www/pages/MessageBoard
In DEC App, the front-end page is the most direct interactive terminal for users. In order to make the front-end interaction as simple as possible, our message board system has only one front-end page, which contains an input area for posting messages and a display area for a message list.
When we need to query the list of objects under a certain path, we can use the list method on the cyfs.GlobalStateAccessStub instance for paging.
The list paging query method here supports paging query by enumerating sub-objects of an objectmap. The range of the queried object list is [size * index, size * (index + 1)]
.
- See src/www/apis/message.ts for the function to initiate a request
Querying the message list is mainly to display the message list after calling the query message list method listMessagesByPage
.
Query the message list
needs to complete the following 3 steps:
- Use the root_state_access_stub method on the stack to get the GlobalStateAccessStub instance
- Call the list method on the GlobalStateAccessStub instance to get the
key value list
undermessages_list
- Traverse the
key value list
, call the retrieveMessage method to initiate aquery message request
, and get the final message object after decoding.
The source code is as follows:
export async function retrieveMessage(msgKey: string) {
const stackWraper = checkStack();
// Create a new Message object
const messageObj = Message.create({
key: msgKey,
content: "",
decId: DEC_ID,
owner: stackWraper.checkOwner(),
});
// make a request
const ret = await stackWraper.postObject(messageObj, MessageDecoder, {
reqPath: ROUTER_PATHS.RETRIEVE_MESSAGE,
decId: DEC_ID,
});
if (ret.err) {
console.error(`reponse err, ${ret}`);
return null;
}
// Parse out the MessageObject
const msgRawObj = ret.unwrap();
if (msgRawObj) {
const msgObj: MessageItem = {
key: msgRawObj.key,
name: msgRawObj.desc().owner()!.unwrap().to_base_58(),
time: cyfs.bucky_time_2_js_time(msgRawObj.desc().create_time()),
content: msgRawObj.content,
isSelf: msgRawObj
.desc()
.owner()!
.unwrap()
.equals(checkStack().checkOwner()),
};
return msgObj;
}
return null;
}
export async function listMessagesByPage(pageIndex: number) {
const stack = checkStack();
const selfObjectId = stack.checkOwner();
// Get an instance of cyfs.GlobalStateAccessStub
const access = stack.check().root_state_access_stub(selfObjectId);
// Use the list method to list all objects under messages_list
const lr = await access.list("/messages_list", pageIndex, 10);
if (lr.err) {
if (lr.val.code !== cyfs.BuckyErrorCode.NotFound) {
console.error(`list-subdirs in(/messages_list) io failed, ${lr}`);
} else {
console.warn(`list-subdirs in(/messages_list) not found, ${lr}`);
}
return [];
}
const list = lr.unwrap();
const keyList = list.map((item) => item.map!.key);
console.log("keyList: ", keyList);
const msgList = await Promise.all(
keyList.map(async (item) => {
const msg = await retrieveMessage(item);
return msg;
})
);
const retList = msgList.filter((msg) => msg !== null) as MessageItem[];
retList.sort((a, b) => b.time - a.time);
return retList;
}
- See src/www/apis/message.ts for the function to initiate a request
The page element for posting a message contains a text input box
and a Leave A Message
button, see src/www/pages/MessageBoard.
The front-end interaction process is that after entering the text content of the message in the input box, click the Leave A Message
button to publish a new message and refresh the message list.
Post a new message
requires the following 3 steps:
- Create a message object Message
- Initiate a post message request
- Parse the response object
The source code is as follows:
export async function publishMessage(content: string) {
const stackWraper = checkStack();
// create message object
const messageObj = Message.create({
content,
decId: DEC_ID,
owner: stackWraper.checkOwner(),
});
// initiate a post message request
const ret = await stackWraper.postObject(messageObj, ResponseObjectDecoder, {
reqPath: ROUTER_PATHS.PUBLISH_MESSAGE,
decId: DEC_ID,
});
if (ret.err) {
console.error(`reponse err, ${ret}`);
return null;
}
// Parse the ResponseObject object
const r = ret.unwrap();
if (r) {
const retObj = {
err: r.err,
msg: r.msg,
};
console.log(`reponse, ${retObj}`);
return JSON.stringify(retObj);
}
return null;
}
- See src/www/apis/message.ts for the function to initiate a request
The page element for modifying the message is contained in a message message component. There is a Modify
button in the lower right corner of the message message. After clicking this button, a text input box
and a Submit
button are displayed, see src/www/ components/MessageItem.
The front-end interaction process is that after entering the text content of the message in the input box, click the Submit
button to change the content of the current message and refresh the message list.
Modify a message
requires the following 3 steps:
- Create a message object Message based on the key value of the message object to be modified and the new content content
- Initiate an update message request
- Parse the response object
The source code is as follows:
export async function updateMessage(msgKey: string, content: string) {
const stackWraper = checkStack();
// Create a message object based on the key value of the current message object and the new content content
const MessageObj = Message.create({
key: msgKey,
content,
decId: DEC_ID,
owner: stackWraper.checkOwner(),
});
// initiate an update message request
const ret = await stackWraper.postObject(MessageObj, ResponseObjectDecoder, {
reqPath: ROUTER_PATHS.UPDATE_MESSAGE,
decId: DEC_ID,
});
if (ret.err) {
console.error(`reponse err, ${ret}`);
return null;
}
// Parse the ResponseObject object
const r = ret.unwrap();
if (r) {
const retObj = {
err: r.err,
msg: r.msg,
};
console.log(`reponse, ${retObj}`);
return JSON.stringify(retObj);
}
return null;
}
- See src/www/apis/message.ts for the function to initiate a request
The page element for deleting a message is contained in a message component with a red Delete
button in the lower right corner of the message, see src/www/components/MessageItem.
The front-end interaction process is that after clicking the Delete
red button, the current message is deleted and the message list is refreshed.
Deleting a message
requires the following 3 steps:
- Create a message object Message according to the key value of the message object to be deleted currently
- Initiate a delete message request
- Parse the response object
The source code is as follows:
export async function deleteMessage(msgKey: string) {
const stackWraper = checkStack();
// Create a message object Message based on the key value of the current message object
const MessageObj = Message.create({
key: msgKey,
content: "",
decId: DEC_ID,
owner: stackWraper.checkOwner(),
});
// initiate a delete message request
const ret = await stackWraper.postObject(MessageObj, ResponseObjectDecoder, {
reqPath: ROUTER_PATHS.DELETE_MESSAGE,
decId: DEC_ID,
});
if (ret.err) {
console.error(`reponse err, ${ret}`);
return null;
}
// Parse the ResponseObject object
const r = ret.unwrap();
if (r) {
const retObj = {
err: r.err,
msg: r.msg,
};
console.log(`reponse, ${retObj}`);
return JSON.stringify(retObj);
}
return null;
}
In the project root directory, open a terminal and enter the following command:
npm run dev
Visit http://localhost:8088 in the CYFS browser to see the front-end interface.
Through the previous study, we have implemented a front-end display page for the message board. Now we publish to OOD along with the frontend page and dec_service.
Open the cyfs.config.json
file in the root directory, first modify the version number of version
, we +1 to the version number. Then modify the web
configuration as follows:
{
"version": "1.0.1",
"web": {
"folder": "src/www/dist",
"entry": "index.html"
}
}
Our front end is developed using the React framework and packaged using webpack. In the project root directory, open a terminal and run the following command:
npm run build
After the command is executed, you can see the new dist and deploy folders in the project root directory:
- dist: Front-end packaging product, generated by webpack.
- deploy: the folder published to OOD, including all ts files in the project compiled js files, configured by tsconfig.json
We first open the CYFS browser and run the following command:
- mac
npm run mac-deploy-pre
npm run deploy
- windows
npm run deploy
Finally, the terminal will display the uploaded information. After the upload is complete, the terminal will display the following information:
Upload DecApp Finished.
CYFS App Install Link: cyfs://5r4MYfFbqqyqoA4RipKdGEKQ6ZSX3JzNRaEpMPKiKWAQ/9tGpLNnbNtojWgQ3GmU2Y7byFm7uHDr1AH2FJBoGt5YF
Congratulations, it means our DEC App has been successfully published to OOD.
Please copy the link corresponding to CYFS App Install Link
, we will use this link to install the DEC App in the next section.
- Open the DEC App Store page (cyfs://static/DecAppStore/app_store_list.html) in the CYFS browser, click the
Installed
green button at the top of the page, you will see an extra ` at the end of the app name Update the little green icon, we click on this little green icon to enter the application details page. - On the
App details page
, we can see the latest version of the current DEC App after clickingSelect Update Version
, and click theInstall
green button. - Go back to the
DEC App Store page
(cyfs://static/DecAppStore/app_store_list.html), click theInstalled
green button at the top of the page, you can see the installed dec_service. If it saysInstalling
, please wait patiently for a while. - After the installation is complete, there is a green
enter
sign on the upper right of the application information bar, which is theentrance of the front-end page
, we can click this icon to see the entry page of the DEC App!
Through the study of this chapter, you have basically mastered the knowledge of DEC App front-end development. So far, our message board DEC App is finally complete, it already has a front-end page that looks good and a Serice that runs normally after you have carefully debugged it. I guess you can't wait to share your message board DEC App with your friends to experience it! I totally understand your excitement, but before that, please study the content of the next chapter.