repositories
{
google()
mavenCentral()
maven {
url "https://maven.zohodl.com/"
}
maven {
url "https://downloads.zohocdn.com/wmslibrary"
}
}
dependencies { implementation 'com.zoho.desk:asapsdk:3.0_BETA_13' }
import android.app.Application;
import com.zoho.desk.asap.api.ZohoDeskPortalSDK;
public class MyApplication extends Application {
public static ZohoDeskPortalSDK apiProvider;
@Override
public void onCreate() {
super.onCreate();
ZohoDeskPortalSDK.Logger.enableLogs();
apiProvider = ZohoDeskPortalSDK.getInstance(getApplicationContext());
apiProvider.initDesk(orgId, appId, datacenterValue);
}
}
ZDPortalHome.show(MainActivity.this);
ZDPHomeConfiguration config = new ZDPHomeConfiguration.Builder()
.isKBEnabled(true)
.isCommunityEnabled(true)
.isLiveChatEnabled(true)
.isMyTicketsEnabled(true).build();
ZDPortalHome.setConfiguration(config);
ZDPortalHome.show(activity);
ZDPortalChat.show(activity);
ZDPortalChatUser chatUser = new ZDPortalChatUser();
chatUser.setName(name);
chatUser.setEmail(email);
chatUser.setPhone(phone);
ZDPortalChat.setGuestUserDetails(chatUser);
ZDPortalKB.show(activity);
ZDPortalSubmitTicket.show(activity);
ZDPortalTickets.show(activity);
ZDPortalCommunity.show(activity);
ZDPortalLiveChat.show(<activity>);
ZDPortalLiveChat.getChatFragment()
if(!MyApplication.deskInstance.isUserSignedIn()) {
MyApplication.deskInstance.setUserToken(token, new ZDPortalCallback.SetUserCallback() {
@Override
public voidonUserSetSuccess() {
//User set success
}
@Override
public voidonException(ZDPortalException e) {
//Exception
}
}, isJWT);
}
Token | Definition | Authentication Flow |
usertoken | encrypted unique information that identifies the user (email address, for example) | old flow |
jwttoken | passed from your app. kindly refer for how to generate jwttoken | new flow |
boolean isUserLoggedIn = MyApplication.deskInstance.isUserSignedIn();
To log a user out from the SDK, use the following method.
MyApplication.deskPortalSDK.logout
(new ZDPortalCallback.LogoutCallback()
{
@Override
public void onLogoutSuccess()
{
//User logged out
}
@Override
public void onException(ZDPortalException e)
{
}
});
All the data stored locally in the device is automatically cleared when an authenticated user signs out from the ASAP add-on.
However, if local data needs to be cleared for anonymous users as well, use the following method.
MyApplication.deskInstance.clearDeskPortalData();
The ASAP SDK provides you with the option to customize the UI of the add-on as required.
The SDK UI comes with two predefined themes: light and dark.
(i) Customize theme type:
You can customize the theme type in the SDK add-on using the below code:
ZDPortalConfiguration.setThemeType(ZDPThemeType.SYSTEM);
ZDPThemeType.SYSTEM: By default, the system theme is selected. If you want to change the theme to light/dark mode, use the following methods:
ZDPThemeType.Light : Changes the SDK add-on theme to light irrespective of the system theme.
ZDPThemeType.Dark: Changes the SDK add-on theme to dark irrespective of the system theme.
(ii) Customize colors in the particular theme:
To customize the colors of the particular theme, please use the following method,
ZDPTheme theme = new ZDPTheme.Builder(true)
.setColorPrimary(Color.parseColor("#"))
.setColorAccent(Color.parseColor("#"))
.build();
ZDPortalConfiguration.setThemeBuilder(theme);
The following picture illustrates the color properties for a screen,
ZDPortalConfiguration.setFontBuilder(ZDPFont.Builder().setMedium(medium).setRegular(regular).build())
ZDPortalConfiguration.setLanguage("en");
Language | Locale Code |
English (UK) | en-GB |
English (US) | en-US |
German | de |
Spanish | es |
Catalan | ca |
French | fr |
French (Canada) | fr-ca |
Italian | it |
Russian | ru |
Chinese | zh |
Chinese (Taiwan) | zh-tw |
Turkish | tr |
Dutch | nl |
Danish | da |
Portuguese | pt |
Japanese | ja |
Swedish | sv |
Polish | pl |
Arabic | ar |
Hebrew | he |
Afrikaans | af |
Czech | cs |
Bulgarian | bg |
Finnish | fi |
Greek | el |
Hungarian | hu |
Indonesian | id |
Norwegian (Bokmal) | nb |
Romanian | ro |
Thai | th |
Ukrainian | uk |
Vietnamese | vi |
Urdu | ur |
Hindi | hi |
Telugu | te |
Kannada | kn |
Tamil | ta |
Marathi | mr |
Korean | ko |
Persian | fa |
Bengali | bn |
Gujarati | gu |
Malay | ms |
Malayalam | ml |
Slovak | sk |
Croatian | hr |
Slovenian | sl |
android {
defaultConfig {
...
resConfigs "en", "ta", "fi"
}
}
Key | Default Text | Description |
DeskPortal.Dashboard.Heading | "Customer Support" | Text that appears on the help center dashboard |
DeskPortal.Dashboard.helpcenter.title | "Knowledge Base" | Title of the knowledge base module icon on the dashboard |
DeskPortal.Dashboard.helpcenter.description | "Browse our extensive repository of help articles" | Text that describes the knowledge base |
DeskPortal.Dashboard.community.title | "Community" | Title of the user community module icon on the dashboard |
DeskPortal.Dashboard.community.description | "Find and share solutions with the user community" | Text that describes the user community |
DeskPortal.Dashboard.addticket.title | "Submit Ticket" | Title of the ticket submission module icon on the dashboard |
DeskPortal.Dashboard.addticket.description | "Seek help from our agents" | Text that describes the ticket submission screen |
DeskPortal.Dashboard.myticket.title | "My Tickets" | Title of the my tickets icon on the dashboard |
DeskPortal.Dashboard.myticket.description | "View and manage tickets that you submitted" | Text that describes the my tickets screens |
DeskPortal.Helpcenter.article.detail.relatedtitle | "Related Articles" | Text that appears below any help article in the knowledge base |
DeskPortal.Helpcenter.article.detail.vote.description | "Was this article helpful?" | Text that seeks feedback from the user |
DeskPortal.Helpcenter.feedback.title | "Feedback" | Title of the feedback form |
DeskPortal.Helpcenter.feedback.description | "We're sorry the article wasn't helpful." | Text that appears when a user downvotes an article |
DeskPortal.Myticket.option.closeticket | "Close Ticket" | Text for option that lets the user close a ticket they submitted |
DeskPortal.Error.message.reload | "Retry" | Error message that appears if ticket submission fails |
DeskPortal.Network.failed.error.message | "No Internet connection" | Error message that indicates loss of connectivity |
DeskPortal.Dashboard.livechat.title | "Live Chat" | Title of the live chat module on the help center dashboard |
DeskPortal.Addticket.title | "Add Ticket" | Title of the ticket submission form |
MyApplication.deskInstance.enablePush("fcmId");
MyApplication.deskInstance.disablePush("fcmId");
ZDPortalConfiguration.handleNotification(Context context, Map data, int icon);
ZDPortalTicketsAPI.createTicket(new CreateTicketCallback() {
@Override
public void onTicketCreated(Ticket ticket) {
}
@Override
public void onException(ZDPortalException exception) {
}
}, ticketData, params);
ZDPortalAPI.getDepartments(new ZDPortalCallback.DepartmensCallback() {
@Override
public void onDepartmentsDownloaded(DepartmentsList response) {
}
@Override
public void onException(ZDPortalException exception) {
}
});
To fetch the IDs of the layout in your help desk portal, use the following method.
HashMap<String, String> params = new HashMap<>();
params.put("departmentId", departmentId);
ZDPortalAPI.getLayouts(new ZDPortalCallback.LayoutsCallback() {
@Override
public void onLayoutsDownloaded(Layouts layouts) {
//layout fetch succeed
}
@Override
public void onException(ZDPortalException e) {
//layout fetch failed
}
}, params);
HashMap<String, String> options = new HashMap<>();
options.put("from", String.valueOf(1));
options.put("limit", String.valueOf(100));
options.put("departmentId", departmentId);
ZDPortalAPI.getProductsList(new ZDPortalCallback.ProductsCallback() {
@Override
public void onProductsDownloaded(ProductsList productsList) {
productsMap.put(departmentId, productsList.getData());
responseLiveData.setValue(productsList.getData());
}
@Override
public void onException(ZDPortalException exception) {
}
}, options);
ZDPortalTicketsAPI.getTicketFields(new TicketFieldsCallback() {
@Override
public void onTicketFieldsDownloaded(TicketFieldsList ticketFieldsList) {
}
@Override
public void onException(ZDPortalException exception) {
}
}, fieldsParams, "apiName");
ZDPortalTicketsAPI.uploadAttachment(new UploadAttachmentCallback() {
@Override
public void onAttachmentUploaded(ASAPAttachmentUploadResponse response) {
}
@Override
public void onException(ZDPortalException exception) {
}
}, fileTobeUploaded, null);
ZDPortalKB.showCategoryWithPermalink(activity, permaLink);
ZDPortalKB.showArticleWithPermalink(activity, permaLink);
ZDPCommunityConfiguration configuration = new ZDPCommunityConfiguration.Builder()
.isReplyAllowed(true)
.isReplyEditAllowed(true)
.isReplyDeleteAllowed(true)
.isTopicEditAllowed(true)
.isTopicDeleteAllowed(true).build();
ZDPortalCommunity.setConfiguration(configuration);
HashMap<String, String> params = new HashMap<>();
params.put("from", "1");
params.put("limit", "5");
ZDPortalCommunityAPI.getMostPopularTopics(new ZDPortalCallback.CommunityTopicsCallback() {
@Override
public void onCommunityTopicsDownloaded(DeskTopicsList deskTopicsList) {
}
@Override
public void onException(ZDPortalException e) {
}
}, params);
HashMap<String, String> params = new HashMap<>();
params.put("from", "1");
params.put("limit", "5");
ZDPortalCommunityAPI.getMostDiscussedTopics(new
ZDPortalCallback.CommunityTopicsCallback()
{
@Override
public void onCommunityTopicsDownloaded(DeskTopicsList deskTopicsList)
{
}
@Override
public void onException(ZDPortalException e)
{
}
}, params);
ZDPortalSubmitTicket.setTicketsFieldsListTobeShown(ticketListTobeShown, deptId,
layoutId);
ZDPortalSubmitTicket.preFillTicketFields(preFillTicketFields, deptId, layoutId);
ZDPortalSubmitTicket.setCreateTicketCallback(new ZDPortalCallback.CreateTicketCallback()
{
@Override
public void onTicketCreated(Ticket ticket)
{
//Ticket created
}
@Override
public void onException(ZDPortalException e)
{
//Exception
}
});
ZDPTicketConfiguration configuration = new ZDPTicketConfiguration.Builder()
.isReplyAllowed(true)
.isCommentAllowed(true)
.isCommentEditAllowed(true)
.isTicketUpdateAllowed(true)
.build();
ZDPortalTickets.setConfiguration(configuration);
HashMap<String, String> params = new HashMap<>();
params.put("timeZone", "asia/kolkatta");
ZDPortalAPI.updateProfileDetails(new ZDPortalCallback.UserDetailsCallback() {
@Override
public void onUserDetailsSuccess(DeskUserProfile userProfile) {
}
@Override
public void onException(ZDPortalException exception) {
}
}, params);
Params
ZDPortalConfiguration.setConfiguration(new ZDPConfiguration.Builder().isKBEnabled(false).build())
Method name | Functions | Details of the default enabled/disabled status |
isCommunityEnabled | To hide the Community module | based on Portal configuration |
isMyTicketsEnabled | To hide the My Tickets module | based on Portal configuration |
isSubmitTicketEnabled | To hide the Add Ticket module | based on Portal configuration |
isAddTopicEnabled | To hide the Add Topic module | based on Portal configuration |
isChatBotEnabled | To hide the Chat Bot module | based on Portal configuration |
isLiveChatEnabled | To hide the Agent C module | based on Portal configuration |
isSideMenuEnabled | To disable the Side Menu option | enabled |
isPoweredByFooterEnabled | To hide the powered by ASAP label button | enabled |
isLangChooserEnabled | To disable the language chooser option | enabled |
isAttachmentDownloadEnabled | To disable the Download attachments option | enabled |
isGlobalSearchEnabled | To disable the Search option | enabled |
isAttachmentUploadEnabled | To disable the Upload attachments option | enabled |
isShareEnabled | To disable the Share option | enabled |
ZohoDeskPortalSDK.Logger.enableLogs();
In this version, the ZDPortalSubmitTicket.show(activity, callback) method has been removed. Please use the
The following enhancements were made to the UI:
Included a header in the Side Menu.
Changed the color of the Default Light and Dark Theme.
Migrating from v2.x to v3.0
Customizing the add-on UI
ZDPortalConfiguration.setThemeResource(themeId); | ZDPortalConfiguration.setThemeType(ZDPThemeType.LIGHT); ZDPortalConfiguration.setThemeBuilder(new ZDPTheme.Builder(false) .setColorPrimary(getResources().getColor(R.color.colorPrimary)) .setColorPrimaryDark(getResources().getColor(R.color.colorPrimaryDark)) .build()); |
Custom-Configuring Community Actions
ZDPCommunityConfiguration communityConfiguration = new ZDPCommunityConfiguration(); communityConfiguration.setTopicEditAllowed(false);
ZDPortalCommunity.setConfiguration(communityConfiguration); | ZDPCommunityConfiguration communityConfiguration = new ZDPCommunityConfiguration.Builder().isTopicEditAllowed(false).build(); ZDPortalCommunity.setConfiguration(communityConfiguration); |
Custom-Configuring Ticket Actions
ZDPTicketConfiguration ticketConfiguration = new ZDPTicketConfiguration(); ticketConfiguration.setReplyAllowed(false);
ZDPortalTickets.setConfiguration(ticketConfiguration); | ZDPTicketConfiguration ticketConfiguration = new ZDPTicketConfiguration.Builder().isReplyAllowed(false).build();
ZDPortalTickets.setConfiguration(ticketConfiguration); |
repositories { jcenter() google() maven { url 'http://maven.zohodl.com/' } maven { url 'https://downloads.zohocdn.com/wmslibrary' }}
dependencies { implementation 'com.zoho.desk:asapsdk:2.1.7' }
-dontwarn com.squareup.okhttp.** -keep class android.support.v7.widget.SearchView { *; } -dontwarn okhttp3.** -dontwarn okio.** -dontwarn retrofit2.** -dontwarn com.zoho.desk.**
import android.app.Application; import com.zoho.desk.asap.api.ZohoDeskPortalSDK; public class MyApplication extends Application { public static ZohoDeskPortalSDK apiProvider; @Override public void onCreate() { super.onCreate(); ZohoDeskPortalSDK.Logger.enableLogs(); apiProvider = ZohoDeskPortalSDK.getInstance(getApplicationContext()); apiProvider.initDesk(orgId, appId, datacenterValue); } }
ZDPortalHome.show(MainActivity.this);
ZDPHomeConfiguration homeConfiguration = new ZDPHomeConfiguration.Builder() .showKB(true) .showMyTickets(true) .showCommunity(true) .showLiveChat(true) .showNavDrawer(true).build(); ZDPortalHome.show(MainActivity.this, homeConfiguration);
ZDPortalChat.show(activity);
ZDPortalChatUser chatUser = new ZDPortalChatUser(); chatUser.setName(name); chatUser.setEmail(email); chatUser.setPhone(phone); ZDPortalChat.setGuestUserDetails(chatUser);
ZDPortalKB.show(activity);
ZDPortalSubmitTicket.show(activity);
ZDPortalSubmitTicket.show(activity, new ZDPortalCallback.CreateTicketCallback() { @Override public void onTicketCreated(Ticket ticket) { //Ticket created } @Override public void onException(ZDPortalException e) { //Exception } } : null);
ZDPortalTickets.show(activity);
ZDPortalCommunity.show(activity);
ZDPortalLiveChat.show(<activity>);
ZDPortalLiveChat.getChatFragment()
if(!MyApplication.deskInstance.isUserSignedIn()) { MyApplication.deskInstance.setUserToken(userToken, new ZDPortalCallback.SetUserCallback() { @Override public voidonUserSetSuccess() { //User set success } @Override public voidonException(ZDPortalException e) { //Exception } }); }
boolean isUserLoggedIn = MyApplication.deskInstance.isUserSignedIn();
MyApplication.deskPortalSDK.logout(new ZDPortalCallback.LogoutCallback() { @Override public void onLogoutSuccess() { //User logged out } @Override public void onException(ZDPortalException e) { } });
MyApplication.deskInstance.clearDeskPortalData();
ZDPortalConfiguration.setThemeResource(R.style.deskTheme_Light);
ZDPortalConfiguration.setThemeResource(R.style.deskTheme_Dark);
ZDPortalConfiguration.setThemeResource(R.style.deskTheme);
<style name="deskTheme" parent="deskTheme_Light"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary </item> <item name="colorPrimaryDark">@color/colorPrimaryDark </item> <item name="colorAccent">@color/colorAccent </item> <item name="android:fontFamily">@font/dosis_regular </item> </style>
ZDPortalConfiguration.setLanguage("en");
Language | Locale Code |
English (UK) | en-GB |
English (US) | en-US |
German | de |
Spanish | es |
Catalan | ca |
French | fr |
French (Canada) | fr-ca |
Italian | it |
Russian | ru |
Chinese | zh |
Chinese (Taiwan) | zh-tw |
Turkish | tr |
Dutch | nl |
Danish | da |
Portuguese | pt |
Japanese | ja |
Swedish | sv |
Polish | pl |
Arabic | ar |
Hebrew | he |
Afrikaans | af |
Czech | cs |
Bulgarian | bg |
Finnish | fi |
Greek | el |
Hungarian | hu |
Indonesian | id |
Norwegian (Bokmal) | nb |
Romanian | ro |
Thai | th |
Ukrainian | uk |
Vietnamese | vi |
Urdu | ur |
Hindi | hi |
Telugu | te |
Kannada | kn |
Tamil | ta |
Marathi | mr |
Korean | ko |
Persian | fa |
Bengali | bn |
Gujarati | gu |
Malay | ms |
Malayalam | ml |
Slovak | sk |
Croatian | hr |
Slovenian | sl |
android { defaultConfig { ... resConfigs "en", "ta", "fi" } }
Key | Default Text | Description |
DeskPortal.Dashboard.Heading | "Customer Support" | Text that appears on the help center dashboard |
DeskPortal.Dashboard.helpcenter.title | "Knowledge Base" | Title of the knowledge base module icon on the dashboard |
DeskPortal.Dashboard.helpcenter.description | "Browse our extensive repository of help articles" | Text that describes the knowledge base |
DeskPortal.Dashboard.community.title | "Community" | Title of the user community module icon on the dashboard |
DeskPortal.Dashboard.community.description | "Find and share solutions with the user community" | Text that describes the user community |
DeskPortal.Dashboard.addticket.title | "Submit Ticket" | Title of the ticket submission module icon on the dashboard |
DeskPortal.Dashboard.addticket.description | "Seek help from our agents" | Text that describes the ticket submission screen |
DeskPortal.Dashboard.myticket.title | "My Tickets" | Title of the my tickets icon on the dashboard |
DeskPortal.Dashboard.myticket.description | "View and manage tickets that you submitted" | Text that describes the my tickets screens |
DeskPortal.Helpcenter.article.detail.relatedtitle | "Related Articles" | Text that appears below any help article in the knowledge base |
DeskPortal.Helpcenter.article.detail.vote.description | "Was this article helpful?" | Text that seeks feedback from the user |
DeskPortal.Helpcenter.feedback.title | "Feedback" | Title of the feedback form |
DeskPortal.Helpcenter.feedback.description | "We're sorry the article wasn't helpful." | Text that appears when a user downvotes an article |
DeskPortal.Myticket.option.closeticket | "Close Ticket" | Text for option that lets the user close a ticket they submitted |
DeskPortal.Error.message.reload | "Retry" | Error message that appears if ticket submission fails |
DeskPortal.Network.failed.error.message | "No Internet connection" | Error message that indicates loss of connectivity |
DeskPortal.Dashboard.livechat.title | "Live Chat" | Title of the live chat module on the help center dashboard |
DeskPortal.Addticket.title | "Add Ticket" | Title of the ticket submission form |
MyApplication.deskInstance.enablePush("fcmId");
MyApplication.deskInstance.disablePush("fcmId");
ZDPortalConfiguration.handleNotification(Context context, Map data, int icon);
ZDPortalTicketsAPI.createTicket(new CreateTicketCallback() { @Override public void onTicketCreated(Ticket ticket) { } @Override public void onException(ZDPortalException exception) { } }, ticketData, params);
ZDPortalAPI.getDepartments(new ZDPortalCallback.DepartmensCallback() { @Override public void onDepartmentsDownloaded(DepartmentsList response) { } @Override public void onException(ZDPortalException exception) { } });
HashMap<String, String> options = new HashMap<>(); options.put("from", String.valueOf(1)); options.put("limit", String.valueOf(100)); options.put("departmentId", departmentId); ZDPortalAPI.getProductsList(new ZDPortalCallback.ProductsCallback() { @Override public void onProductsDownloaded(ProductsList productsList) { productsMap.put(departmentId, productsList.getData()); responseLiveData.setValue(productsList.getData()); } @Override public void onException(ZDPortalException exception) { } }, options);
ZDPortalTicketsAPI.getTicketFields(new TicketFieldsCallback() { @Override public void onTicketFieldsDownloaded(TicketFieldsList ticketFieldsList) { } @Override public void onException(ZDPortalException exception) { } }, fieldsParams, "apiName");
ZDPortalTicketsAPI.uploadAttachment(new UploadAttachmentCallback() { @Override public void onAttachmentUploaded(ASAPAttachmentUploadResponse response) { } @Override public void onException(ZDPortalException exception) { } }, fileTobeUploaded, null);
ZDPortalKB.showCategoryWithPermalink(activity, permaLink);
ZDPortalKB.showArticleWithPermalink(activity, permaLink);
ZDPCommunityConfiguration communityConfiguration = new ZDPCommunityConfiguration(); communityConfiguration.setTopicEditAllowed(false); communityConfiguration.setTopicDeleteAllowed(false); communityConfiguration.setReplyAllowed(true); communityConfiguration.setReplyEditAllowed(true); communityConfiguration.setReplyDeleteAllowed(false); ZDPortalCommunity.setConfiguration(communityConfiguration);
HashMap<String, String> params = new HashMap<>(); params.put("from", "1"); params.put("limit", "5"); ZDPortalCommunityAPI.getMostPopularTopics(new ZDPortalCallback.CommunityTopicsCallback() { @Override public void onCommunityTopicsDownloaded(DeskTopicsList deskTopicsList) { } @Override public void onException(ZDPortalException e) { } }, params);
HashMap<String, String> params = new HashMap<>(); params.put("from", "1"); params.put("limit", "5"); ZDPortalCommunityAPI.getMostDiscussedTopics(new ZDPortalCallback.CommunityTopicsCallback() { @Override public void onCommunityTopicsDownloaded(DeskTopicsList deskTopicsList) { } @Override public void onException(ZDPortalException e) { } }, params);
ZDPortalSubmitTicket.setTicketsFieldsListTobeShown(ticketListTobeShown, deptId);
ZDPortalSubmitTicket.preFillTicketFields(preFillTicketFields, deptId);
ZDPTicketConfiguration ticketConfiguration = new ZDPTicketConfiguration(); ticketConfiguration.setReplyAllowed(false); ticketConfiguration.setCommentAllowed(true); ticketConfiguration.setTicketUpdateAllowed(true); ticketConfiguration.setCommentEditAllowed(false); ticketConfiguration.setCommentDeleteAllowed(false); ZDPortalTickets.setConfiguration(ticketConfiguration);
HashMap<String, String> params = new HashMap<>(); params.put("timeZone", "asia/kolkatta"); ZDPortalAPI.updateProfileDetails(new ZDPortalCallback.UserDetailsCallback() { @Override public void onUserDetailsSuccess(DeskUserProfile userProfile) { } @Override public void onException(ZDPortalException exception) { } }, params);
ZohoDeskPortalSDK.Logger.enableLogs();
Learn how to use the best tools for sales force automation and better customer engagement from Zoho's implementation specialists.
If you'd like a personalized walk-through of our data preparation tool, please request a demo and we'll be happy to show you how to get the best out of Zoho DataPrep.
Write to us: support@zohoforms.com
Quick Links |
Workflow Automation |
Data Collection |
|
||
Form Templates |
||
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|