webcake-storefront-mcp 1.15.1 → 1.17.0
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.
- package/dist/api.js +465 -0
- package/dist/builder/guide.js +20 -1
- package/dist/builder/page.js +103 -1
- package/dist/changelog.json +14 -14
- package/dist/http.js +2 -1
- package/dist/server.js +7 -44
- package/dist/tools/affiliate.js +27 -0
- package/dist/tools/appointment.js +74 -0
- package/dist/tools/apps-extra.js +44 -0
- package/dist/tools/apps.js +18 -0
- package/dist/tools/builder.js +24 -1
- package/dist/tools/catalog-extras.js +88 -0
- package/dist/tools/marketing.js +74 -0
- package/dist/tools/media.js +39 -0
- package/dist/tools/multilingual.js +70 -0
- package/dist/tools/registry.js +251 -0
- package/dist/tools/reviews.js +58 -0
- package/dist/tools/sale-channels.js +48 -0
- package/dist/tools/site-config.js +98 -0
- package/package.json +5 -3
package/dist/api.js
CHANGED
|
@@ -520,4 +520,469 @@ export class WebcakeCmsApi {
|
|
|
520
520
|
sendMail(params) {
|
|
521
521
|
return this.request("POST", `/api/v1/cms_function/${this.siteId}/application/automation/send_mail`, { body: params });
|
|
522
522
|
}
|
|
523
|
+
// ── App lifecycle (applications/subcriptions) ──
|
|
524
|
+
/** Uninstall an app by its subscription id (the `id` from list_apps / get_app). */
|
|
525
|
+
uninstallApp(id) {
|
|
526
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/applications/subcriptions/uninstall_app`, { body: { id } });
|
|
527
|
+
}
|
|
528
|
+
/** Update an installed app's settings. `attrs` is merged onto the subscription (e.g. { settings: {...}, status }). */
|
|
529
|
+
updateApp(id, attrs) {
|
|
530
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/applications/subcriptions/update_app`, { body: { id, attrs } });
|
|
531
|
+
}
|
|
532
|
+
/** Update the product-review app's settings (shop_info, display options…). */
|
|
533
|
+
updateAppReview(id, settings) {
|
|
534
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/applications/subcriptions/update_app_review`, { body: { id, settings } });
|
|
535
|
+
}
|
|
536
|
+
// ── Product reviews (product_review app) ──
|
|
537
|
+
listReviews(query) {
|
|
538
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/applications/product_reviews/all_review_admin`, { query });
|
|
539
|
+
}
|
|
540
|
+
getReview(reviewId) {
|
|
541
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/applications/product_reviews/${reviewId}`);
|
|
542
|
+
}
|
|
543
|
+
getReviewProducts(reviewId) {
|
|
544
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/applications/product_reviews/products`, { query: { review_id: reviewId } });
|
|
545
|
+
}
|
|
546
|
+
/** Create or update a review/reply. `body` is the review payload (id, customer_info, rating, title,
|
|
547
|
+
* comment, images, parent_id, apply_to, categories, permission, is_shop, product_reviews…). */
|
|
548
|
+
createOrUpdateReview(body) {
|
|
549
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/applications/product_reviews/create_or_update`, { body });
|
|
550
|
+
}
|
|
551
|
+
removeReviews(ids) {
|
|
552
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/applications/product_reviews/remove`, { body: { ids } });
|
|
553
|
+
}
|
|
554
|
+
/** Approve/hide reviews. `payload` typically { ids, permission } (permission 0=approved, 1=pending…). */
|
|
555
|
+
updateReviewStatus(payload) {
|
|
556
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/applications/product_reviews/update_status`, { body: payload });
|
|
557
|
+
}
|
|
558
|
+
// ── Appointment app ──
|
|
559
|
+
listAppointmentCalendars(query) {
|
|
560
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/appointment/appointment_calendars`, { query });
|
|
561
|
+
}
|
|
562
|
+
createAppointmentCalendar(appointment_calendar) {
|
|
563
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/create_appointment_calendar`, { body: { appointment_calendar } });
|
|
564
|
+
}
|
|
565
|
+
updateAppointmentCalendar(appointment_calendar) {
|
|
566
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/update_appointment_calendar`, { body: { appointment_calendar } });
|
|
567
|
+
}
|
|
568
|
+
deleteAppointmentCalendars(ids) {
|
|
569
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/delete_appointment_calendars`, { body: { ids } });
|
|
570
|
+
}
|
|
571
|
+
duplicateAppointmentCalendars(ids) {
|
|
572
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/duplicate_appointment_calendars`, { body: { ids } });
|
|
573
|
+
}
|
|
574
|
+
listAppointments(query) {
|
|
575
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/appointment/appointments`, { query });
|
|
576
|
+
}
|
|
577
|
+
listAppointmentAddresses(query) {
|
|
578
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/appointment/appointment_addresses`, { query });
|
|
579
|
+
}
|
|
580
|
+
createAppointmentAddress(appointment_address) {
|
|
581
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/create_appointment_address`, { body: { appointment_address } });
|
|
582
|
+
}
|
|
583
|
+
updateAppointmentAddress(appointment_address) {
|
|
584
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/update_appointment_address`, { body: { appointment_address } });
|
|
585
|
+
}
|
|
586
|
+
deleteAppointmentAddresses(ids) {
|
|
587
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/delete_appointment_addresses`, { body: { ids } });
|
|
588
|
+
}
|
|
589
|
+
listAppointmentClassifies(query) {
|
|
590
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/appointment/appointment_classifies`, { query });
|
|
591
|
+
}
|
|
592
|
+
createAppointmentClassify(appointment_classify) {
|
|
593
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/create_appointment_classify`, { body: { appointment_classify } });
|
|
594
|
+
}
|
|
595
|
+
updateAppointmentClassify(appointment_classify) {
|
|
596
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/update_appointment_classify`, { body: { appointment_classify } });
|
|
597
|
+
}
|
|
598
|
+
deleteAppointmentClassifies(ids) {
|
|
599
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/delete_appointment_classifies`, { body: { ids } });
|
|
600
|
+
}
|
|
601
|
+
listAppointmentEmployees(query) {
|
|
602
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/appointment/appointment_employees`, { query });
|
|
603
|
+
}
|
|
604
|
+
createAppointmentEmployee(appointment_employee) {
|
|
605
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/create_appointment_employee`, { body: { appointment_employee } });
|
|
606
|
+
}
|
|
607
|
+
updateAppointmentEmployee(appointment_employee) {
|
|
608
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/update_appointment_employee`, { body: { appointment_employee } });
|
|
609
|
+
}
|
|
610
|
+
deleteAppointmentEmployees(ids) {
|
|
611
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/appointment/delete_appointment_employees`, { body: { ids } });
|
|
612
|
+
}
|
|
613
|
+
// ── Affiliate app ──
|
|
614
|
+
getProgramAffiliates() {
|
|
615
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/affiliate/program_affiliates`);
|
|
616
|
+
}
|
|
617
|
+
getProductAffiliates(query) {
|
|
618
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/affiliate/product_affiliates`, { query });
|
|
619
|
+
}
|
|
620
|
+
getOrderAffiliates(query) {
|
|
621
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/affiliate/order_affiliates`, { query });
|
|
622
|
+
}
|
|
623
|
+
getAccountAffiliates(query) {
|
|
624
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/affiliate/account_affiliates`, { query });
|
|
625
|
+
}
|
|
626
|
+
getPayoutAffiliates(query) {
|
|
627
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/affiliate/payout_affiliates`, { query });
|
|
628
|
+
}
|
|
629
|
+
getAffiliateStatistic() {
|
|
630
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/affiliate/statistic`);
|
|
631
|
+
}
|
|
632
|
+
upsertOrderProgramAffiliate(payload) {
|
|
633
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/affiliate/upsert_order_program_affiliate`, { body: payload });
|
|
634
|
+
}
|
|
635
|
+
upsertProductProgramAffiliate(payload) {
|
|
636
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/affiliate/upsert_product_program_affiliate`, { body: payload });
|
|
637
|
+
}
|
|
638
|
+
upsertProductAffiliate(payload) {
|
|
639
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/affiliate/upsert_product_affiliate`, { body: payload });
|
|
640
|
+
}
|
|
641
|
+
deleteProductAffiliates(payload) {
|
|
642
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/affiliate/delete_product_affiliates`, { body: payload });
|
|
643
|
+
}
|
|
644
|
+
updatePayoutAffiliateStatus(payload) {
|
|
645
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/affiliate/update_status_payout_affiliate`, { body: payload });
|
|
646
|
+
}
|
|
647
|
+
deleteAccountAffiliates(payload) {
|
|
648
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/affiliate/delete_account_affiliates`, { body: payload });
|
|
649
|
+
}
|
|
650
|
+
updateAccountAffiliate(payload) {
|
|
651
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/affiliate/update_account_affiliate`, { body: payload });
|
|
652
|
+
}
|
|
653
|
+
// ── Catalog extras (brands / suppliers / tags / ribbons / materials / variations) ──
|
|
654
|
+
listProductBrands() {
|
|
655
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/products/product_brands/all`);
|
|
656
|
+
}
|
|
657
|
+
upsertProductBrand(body) {
|
|
658
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/products/product_brands/create_or_update`, { body });
|
|
659
|
+
}
|
|
660
|
+
listProductSuppliers() {
|
|
661
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/products/product_suppliers/all`);
|
|
662
|
+
}
|
|
663
|
+
upsertProductSupplier(body) {
|
|
664
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/products/product_suppliers/create_or_update`, { body });
|
|
665
|
+
}
|
|
666
|
+
listProductTags(query) {
|
|
667
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/products/product_tags/all`, { query });
|
|
668
|
+
}
|
|
669
|
+
upsertProductTag(body) {
|
|
670
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/products/product_tags/create_or_update`, { body });
|
|
671
|
+
}
|
|
672
|
+
listRibbons() {
|
|
673
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/products/ribbons/all`);
|
|
674
|
+
}
|
|
675
|
+
upsertRibbon(body) {
|
|
676
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/products/ribbons/create_or_update`, { body });
|
|
677
|
+
}
|
|
678
|
+
listMaterials() {
|
|
679
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/products/materials/all`);
|
|
680
|
+
}
|
|
681
|
+
upsertMaterial(body) {
|
|
682
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/products/materials/create_or_update`, { body });
|
|
683
|
+
}
|
|
684
|
+
getVariation(variationId) {
|
|
685
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/products/variation/${variationId}`);
|
|
686
|
+
}
|
|
687
|
+
getProductMeasurement() {
|
|
688
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/settings/product_measurement`);
|
|
689
|
+
}
|
|
690
|
+
updateProductMeasurement(product_measurement) {
|
|
691
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/settings/product_measurement/update`, { body: { product_measurement } });
|
|
692
|
+
}
|
|
693
|
+
listBlockPhoneNumbers(query) {
|
|
694
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/settings/block_phone_number/all`, { query });
|
|
695
|
+
}
|
|
696
|
+
upsertBlockPhoneCustomers(phone_numbers) {
|
|
697
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/settings/block_phone_number/upsert_block_phone_customers`, { body: { phone_numbers } });
|
|
698
|
+
}
|
|
699
|
+
removeAllBlockPhoneCustomers() {
|
|
700
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/settings/block_phone_number/remove_all_block_phone_customers`, { body: {} });
|
|
701
|
+
}
|
|
702
|
+
getPriceContacts(type) {
|
|
703
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/settings/price_contact/get`, { query: { type } });
|
|
704
|
+
}
|
|
705
|
+
updatePriceContact(body) {
|
|
706
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/settings/price_contact/update`, { body });
|
|
707
|
+
}
|
|
708
|
+
getCategoryById(categoryId) {
|
|
709
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/categories/${categoryId}`);
|
|
710
|
+
}
|
|
711
|
+
// ── Site config (domains / redirects / shipping / utms / logs / filters / settings / fonts) ──
|
|
712
|
+
listDomains(query) {
|
|
713
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/domains/all`, { query });
|
|
714
|
+
}
|
|
715
|
+
createDomain(body) {
|
|
716
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/domains/create`, { body });
|
|
717
|
+
}
|
|
718
|
+
updateDomain(body) {
|
|
719
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/domains/update`, { body });
|
|
720
|
+
}
|
|
721
|
+
verifyDomain(domain_id) {
|
|
722
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/domains/verify`, { body: { domain_id } });
|
|
723
|
+
}
|
|
724
|
+
deleteDomain(domain_id) {
|
|
725
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/domains/delete`, { body: { domain_id } });
|
|
726
|
+
}
|
|
727
|
+
checkDomain(domain) {
|
|
728
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/domains/check_domain`, { body: { domain } });
|
|
729
|
+
}
|
|
730
|
+
listRedirectUrls(query) {
|
|
731
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/seos/redirect_urls/all`, { query });
|
|
732
|
+
}
|
|
733
|
+
createRedirectUrl(redirect_url) {
|
|
734
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/seos/redirect_urls/create`, { body: { redirect_url } });
|
|
735
|
+
}
|
|
736
|
+
updateRedirectUrl(redirect_url) {
|
|
737
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/seos/redirect_urls/update`, { body: { redirect_url } });
|
|
738
|
+
}
|
|
739
|
+
deleteRedirectUrls(redirect_url_ids) {
|
|
740
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/seos/redirect_urls/delete`, { body: { redirect_url_ids } });
|
|
741
|
+
}
|
|
742
|
+
getShipping() {
|
|
743
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/settings/shipping`);
|
|
744
|
+
}
|
|
745
|
+
updateShipping(body) {
|
|
746
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/settings/shipping/update`, { body });
|
|
747
|
+
}
|
|
748
|
+
listSiteUtms(query) {
|
|
749
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/site_utms/all`, { query });
|
|
750
|
+
}
|
|
751
|
+
createSiteUtm(site_utm) {
|
|
752
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/site_utms/create`, { body: { site_utm } });
|
|
753
|
+
}
|
|
754
|
+
updateSiteUtm(site_utm) {
|
|
755
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/site_utms/update`, { body: { site_utm } });
|
|
756
|
+
}
|
|
757
|
+
deleteSiteUtms(ids) {
|
|
758
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/site_utms/delete`, { body: { ids } });
|
|
759
|
+
}
|
|
760
|
+
listSystemLogs(query) {
|
|
761
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/system_logs/all`, { query });
|
|
762
|
+
}
|
|
763
|
+
listSavedFilters(table_key) {
|
|
764
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/saved_filters/`, { query: { table_key } });
|
|
765
|
+
}
|
|
766
|
+
createSavedFilter(saved_filter) {
|
|
767
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/saved_filters/create`, { body: { saved_filter } });
|
|
768
|
+
}
|
|
769
|
+
updateSavedFilter(id, saved_filter) {
|
|
770
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/saved_filters/${id}/update`, { body: { saved_filter } });
|
|
771
|
+
}
|
|
772
|
+
deleteSavedFilter(id) {
|
|
773
|
+
return this.request("DELETE", `/api/v1/dashboard/site/${this.siteId}/saved_filters/${id}`);
|
|
774
|
+
}
|
|
775
|
+
/** Raw /update_site call. `body` top-level keys replace; a nested `settings` key is merged server-side. */
|
|
776
|
+
updateSiteRaw(body) {
|
|
777
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/update_site`, { body });
|
|
778
|
+
}
|
|
779
|
+
updateSiteName(name) {
|
|
780
|
+
return this.request("POST", `/api/v1/site/${this.siteId}/update_site_name`, { body: { name } });
|
|
781
|
+
}
|
|
782
|
+
updateSiteSlug(slug) {
|
|
783
|
+
return this.request("POST", `/api/v1/site/${this.siteId}/update_slug_name`, { body: { slug } });
|
|
784
|
+
}
|
|
785
|
+
loadFonts() {
|
|
786
|
+
return this.request("GET", `/api/v1/site/${this.siteId}/load_fonts`);
|
|
787
|
+
}
|
|
788
|
+
removeFont(id) {
|
|
789
|
+
return this.request("DELETE", `/api/v1/site/${this.siteId}/remove_font`, { body: { id } });
|
|
790
|
+
}
|
|
791
|
+
loadFontGroups() {
|
|
792
|
+
return this.request("GET", `/api/v1/site/${this.siteId}/load_font_groups`);
|
|
793
|
+
}
|
|
794
|
+
createFontGroup(body) {
|
|
795
|
+
return this.request("POST", `/api/v1/site/${this.siteId}/create_font_group`, { body: { ...body, site_id: this.siteId } });
|
|
796
|
+
}
|
|
797
|
+
removeFontGroup(id) {
|
|
798
|
+
return this.request("DELETE", `/api/v1/site/${this.siteId}/remove_font_groups`, { body: { id, site_id: this.siteId } });
|
|
799
|
+
}
|
|
800
|
+
listApiKeys(query) {
|
|
801
|
+
return this.request("GET", `/api/v1/site/${this.siteId}/api_keys/all`, { query });
|
|
802
|
+
}
|
|
803
|
+
listPublishHistories(query) {
|
|
804
|
+
return this.request("GET", `/api/v1/site/${this.siteId}/publish_histories`, { query });
|
|
805
|
+
}
|
|
806
|
+
// ── Marketing / CRM / team ──
|
|
807
|
+
getSendEmail() {
|
|
808
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/send_email/all`);
|
|
809
|
+
}
|
|
810
|
+
saveSendEmail(body) {
|
|
811
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/send_email/save`, { body });
|
|
812
|
+
}
|
|
813
|
+
listContacts(query) {
|
|
814
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/contact/all`, { query });
|
|
815
|
+
}
|
|
816
|
+
createContact(body) {
|
|
817
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/contact/create`, { body: { ...body, site_id: this.siteId } });
|
|
818
|
+
}
|
|
819
|
+
deleteContacts(ids) {
|
|
820
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/contact/delete`, { body: { ids } });
|
|
821
|
+
}
|
|
822
|
+
listSubscribers(query) {
|
|
823
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/subscriber/all`, { query });
|
|
824
|
+
}
|
|
825
|
+
createSubscriber(body) {
|
|
826
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/subscriber/create`, { body });
|
|
827
|
+
}
|
|
828
|
+
deleteSubscribers(ids) {
|
|
829
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/subscriber/delete`, { body: { ids } });
|
|
830
|
+
}
|
|
831
|
+
listEmployees() {
|
|
832
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/settings/employee/all`);
|
|
833
|
+
}
|
|
834
|
+
inviteEmployee(email) {
|
|
835
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/settings/employee/invite`, { body: { email } });
|
|
836
|
+
}
|
|
837
|
+
updateEmployeePermissions(site_permission) {
|
|
838
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/settings/employee/change_permissions`, { body: { site_permission } });
|
|
839
|
+
}
|
|
840
|
+
deleteEmployees(site_permission_ids) {
|
|
841
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/settings/employee/delete_employees`, { body: { site_permission_ids } });
|
|
842
|
+
}
|
|
843
|
+
listInvitations() {
|
|
844
|
+
return this.request("GET", `/api/v1/dashboard/site/invitations/all`);
|
|
845
|
+
}
|
|
846
|
+
acceptInvitation(invitation_id) {
|
|
847
|
+
return this.request("POST", `/api/v1/dashboard/site/invitations/accept`, { body: { invitation_id } });
|
|
848
|
+
}
|
|
849
|
+
refuseInvitation(invitation_id) {
|
|
850
|
+
return this.request("POST", `/api/v1/dashboard/site/invitations/refuse`, { body: { invitation_id } });
|
|
851
|
+
}
|
|
852
|
+
listCustomerTags() {
|
|
853
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/customer/customer_tags`);
|
|
854
|
+
}
|
|
855
|
+
upsertCustomerTag(body) {
|
|
856
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/customer/upsert_customer_tag`, { body: { ...body, site_id: this.siteId } });
|
|
857
|
+
}
|
|
858
|
+
assignCustomerTags(body) {
|
|
859
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/customer/update_tags_for_multiple_customers`, { body: { ...body, site_id: this.siteId } });
|
|
860
|
+
}
|
|
861
|
+
getInsightToday() {
|
|
862
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/insight/today`);
|
|
863
|
+
}
|
|
864
|
+
getInsight(query) {
|
|
865
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/insight/all`, { query });
|
|
866
|
+
}
|
|
867
|
+
listNotifications() {
|
|
868
|
+
return this.request("GET", `/api/v1/dashboard/site/notifications/all`);
|
|
869
|
+
}
|
|
870
|
+
markNotificationRead(notification_id) {
|
|
871
|
+
return this.request("POST", `/api/v1/dashboard/site/notifications/mark_as_read`, { body: { notification_id } });
|
|
872
|
+
}
|
|
873
|
+
// ── Multilingual / translations ──
|
|
874
|
+
mlAddLanguages(languages) {
|
|
875
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/multilingual/add_multiple_language`, { body: { languages } });
|
|
876
|
+
}
|
|
877
|
+
mlChangeDefault(language_code) {
|
|
878
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/multilingual/change_language_default`, { body: { language_code } });
|
|
879
|
+
}
|
|
880
|
+
mlGetTranslations(resource, query) {
|
|
881
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/multilingual/${resource}`, { query });
|
|
882
|
+
}
|
|
883
|
+
mlSaveTranslations(action, body) {
|
|
884
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/multilingual/${action}`, { body });
|
|
885
|
+
}
|
|
886
|
+
mlTranslateJson(body) {
|
|
887
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/multilingual/translate_json`, { body });
|
|
888
|
+
}
|
|
889
|
+
// ── Media library + PWA ──
|
|
890
|
+
listMediaFolders(query) {
|
|
891
|
+
return this.request("GET", `/api/v1/site/${this.siteId}/media/folder`, { query });
|
|
892
|
+
}
|
|
893
|
+
listMediaContent(query) {
|
|
894
|
+
return this.request("GET", `/api/v1/site/${this.siteId}/media/content`, { query });
|
|
895
|
+
}
|
|
896
|
+
listMediaAll(query) {
|
|
897
|
+
return this.request("GET", `/api/v1/site/${this.siteId}/media/all`, { query });
|
|
898
|
+
}
|
|
899
|
+
getMediaCapacity() {
|
|
900
|
+
return this.request("GET", `/api/v1/site/${this.siteId}/media/capacity`);
|
|
901
|
+
}
|
|
902
|
+
emptyMediaTrash() {
|
|
903
|
+
return this.request("POST", `/api/v1/site/${this.siteId}/media/empty_trash`, { body: {} });
|
|
904
|
+
}
|
|
905
|
+
uploadBase64Media(base64) {
|
|
906
|
+
return this.request("POST", `/api/v1/site/${this.siteId}/media/content/b64`, { body: { base64 }, timeout: 60000 });
|
|
907
|
+
}
|
|
908
|
+
updateMediaFolder(body) {
|
|
909
|
+
return this.request("POST", `/api/v1/site/${this.siteId}/media/folder/update`, { body });
|
|
910
|
+
}
|
|
911
|
+
updateMediaContent(body) {
|
|
912
|
+
return this.request("POST", `/api/v1/site/${this.siteId}/media/content/update`, { body });
|
|
913
|
+
}
|
|
914
|
+
getPwa() {
|
|
915
|
+
return this.request("GET", `/api/v1/site/${this.siteId}/pwa`);
|
|
916
|
+
}
|
|
917
|
+
upsertPwa(body) {
|
|
918
|
+
return this.request("POST", `/api/v1/site/${this.siteId}/pwa/upsert`, { body });
|
|
919
|
+
}
|
|
920
|
+
// ── Apps: product design / personal product design / course ──
|
|
921
|
+
getDeviceTemplates() {
|
|
922
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/applications/product_design/get_group_device_tempalte`);
|
|
923
|
+
}
|
|
924
|
+
createProductsByDeviceTemplate(groups) {
|
|
925
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/applications/product_design/create_product_by_device_template`, { body: { groups, site_id: this.siteId } });
|
|
926
|
+
}
|
|
927
|
+
getAllPpd(query) {
|
|
928
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/applications/personal_product_design/get_all_ppd`, { query });
|
|
929
|
+
}
|
|
930
|
+
upsertPpd(ppds) {
|
|
931
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/applications/personal_product_design/upsert_ppd`, { body: { ppds, site_id: this.siteId } });
|
|
932
|
+
}
|
|
933
|
+
removePpd(ids) {
|
|
934
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/applications/personal_product_design/remove_ppd`, { body: { ids, site_id: this.siteId } });
|
|
935
|
+
}
|
|
936
|
+
getProductVariationTemplate(product_id) {
|
|
937
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/applications/personal_product_design/get_product_variation_template`, { query: { product_id } });
|
|
938
|
+
}
|
|
939
|
+
listCourses(query) {
|
|
940
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/course-app`, { query });
|
|
941
|
+
}
|
|
942
|
+
getCourse(id) {
|
|
943
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/course-app/${id}`);
|
|
944
|
+
}
|
|
945
|
+
createCourse(body) {
|
|
946
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/course-app`, { body: { ...body, site_id: this.siteId } });
|
|
947
|
+
}
|
|
948
|
+
updateCourse(id, body) {
|
|
949
|
+
return this.request("PATCH", `/api/v1/dashboard/site/${this.siteId}/course-app/${id}`, { body });
|
|
950
|
+
}
|
|
951
|
+
deleteCourse(id) {
|
|
952
|
+
return this.request("DELETE", `/api/v1/dashboard/site/${this.siteId}/course-app/${id}`);
|
|
953
|
+
}
|
|
954
|
+
deleteManyCourses(ids) {
|
|
955
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/course-app/delete_many`, { body: { ids, site_id: this.siteId } });
|
|
956
|
+
}
|
|
957
|
+
getCourseMembers(query) {
|
|
958
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/course-app/members`, { query });
|
|
959
|
+
}
|
|
960
|
+
// ── Sale channels: sitemap + partner feeds + catalogs ──
|
|
961
|
+
sitemapSync(kind) {
|
|
962
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/sale_channels/sitemap/sync_${kind}`, { body: {} });
|
|
963
|
+
}
|
|
964
|
+
sitemapRebuild(type) {
|
|
965
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/sale_channels/sitemap/rebuild`, { body: { type } });
|
|
966
|
+
}
|
|
967
|
+
listPartnerFeeds(query) {
|
|
968
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/sale_channels/partner_feeds/all`, { query });
|
|
969
|
+
}
|
|
970
|
+
createPartnerFeed(body) {
|
|
971
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/sale_channels/partner_feeds/create`, { body });
|
|
972
|
+
}
|
|
973
|
+
updatePartnerFeed(partnerFeedId, body) {
|
|
974
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/sale_channels/partner_feeds/${partnerFeedId}/update`, { body });
|
|
975
|
+
}
|
|
976
|
+
deletePartnerFeeds(partner_feed_ids) {
|
|
977
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/sale_channels/partner_feeds/delete`, { body: { partner_feed_ids } });
|
|
978
|
+
}
|
|
979
|
+
listPartnerFeedProducts(partnerFeedId, query) {
|
|
980
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/sale_channels/partner_feeds/${partnerFeedId}/products/all`, { query });
|
|
981
|
+
}
|
|
982
|
+
syncPartnerFeed(partnerFeedId) {
|
|
983
|
+
return this.request("POST", `/api/v1/dashboard/site/${this.siteId}/sale_channels/partner_feeds/${partnerFeedId}/products/sync`, { body: { partner_feed_id: partnerFeedId } });
|
|
984
|
+
}
|
|
985
|
+
listGoogleMerchants(query) {
|
|
986
|
+
return this.request("GET", `/api/v1/dashboard/site/${this.siteId}/sale_channels/google/merchants`, { query });
|
|
987
|
+
}
|
|
523
988
|
}
|
package/dist/builder/guide.js
CHANGED
|
@@ -36,7 +36,26 @@ children with a grid:
|
|
|
36
36
|
- each child config also has \`rowStart/rowEnd\` (1-based grid lines),
|
|
37
37
|
\`constraintX\` (['left'|'right'|'centerLeft']), \`constraintY\` (['top'|'bottom'|'centerTop']).
|
|
38
38
|
new_section does ALL of this for you: pass children and they are stacked one row each in
|
|
39
|
-
the centre column.
|
|
39
|
+
the centre column.
|
|
40
|
+
|
|
41
|
+
## Multi-column rows (cards side by side) — USE THIS, real pages are full of them
|
|
42
|
+
A plain vertical stack looks like a blog post, not a designed page. Feature cards,
|
|
43
|
+
category tiles, footer columns, a text+image hero — all are HORIZONTAL rows. Two ways:
|
|
44
|
+
- new_row(children=[colA, colB, colC]) → a container whose children sit SIDE BY SIDE in
|
|
45
|
+
equal columns. Place the returned node as a child of a section.
|
|
46
|
+
- Inside new_section, add \`layout:"row"\` to a CONTAINER child spec and its children become
|
|
47
|
+
columns: \`{ type:"container", layout:"row", children:[ {..}, {..}, {..} ] }\`.
|
|
48
|
+
Rows are RESPONSIVE automatically: finalizeForRender collapses them on small screens
|
|
49
|
+
(default tablet=2 columns, mobile=1) so cards never shrink to slivers — override with
|
|
50
|
+
\`collapse:{bp3:2,bp4:1}\`. Uneven columns via \`colWidths\` (e.g. a 2:1 text/image split:
|
|
51
|
+
\`colWidths:[{unit:'fr',value:2},{unit:'fr',value:1}]\`), spacing via \`columnGap\`/\`rowGap\`.
|
|
52
|
+
Each column is usually a \`container\` holding its own stacked children (image + title +
|
|
53
|
+
text). Example feature row:
|
|
54
|
+
\`new_row(children=[
|
|
55
|
+
{ type:"container", children:[ {type:"image",opts:{...}}, {type:"text",opts:{text:"Giao nhanh"}} ] },
|
|
56
|
+
{ type:"container", children:[ {type:"image",opts:{...}}, {type:"text",opts:{text:"Chất lượng"}} ] },
|
|
57
|
+
{ type:"container", children:[ {type:"image",opts:{...}}, {type:"text",opts:{text:"Bảo hành"}} ] },
|
|
58
|
+
])\`
|
|
40
59
|
|
|
41
60
|
## Where layout/style live: per-breakpoint keys (NOT \`runtime\`)
|
|
42
61
|
new_section / new_element emit a temporary \`runtime: { style, config }\`. That is a
|
package/dist/builder/page.js
CHANGED
|
@@ -84,6 +84,68 @@ export function stackChildren(container, children, opts = {}) {
|
|
|
84
84
|
container.children = children;
|
|
85
85
|
return container;
|
|
86
86
|
}
|
|
87
|
+
const ROW_PLACEHOLDER_ROW = () => ({ unit: "min/max", min: { unit: "px", absValue: 50 }, max: { unit: "max-c" } });
|
|
88
|
+
/** Default responsive collapse for a multi-column row: full columns on desktop/laptop,
|
|
89
|
+
* 2 columns on tablet, 1 column on mobile. `null` = keep the full column count. */
|
|
90
|
+
const ROW_COLLAPSE_DEFAULT = { bp1: null, bp2: null, bp3: 2, bp4: 1 };
|
|
91
|
+
/**
|
|
92
|
+
* Lay children out HORIZONTALLY — side by side in one grid row — the way real BuilderX
|
|
93
|
+
* pages build feature cards, category tiles, footer columns, 2-col hero, etc. The grid is
|
|
94
|
+
* `Nx1` with N equal `fr` columns and each child placed in its own column. Values go to
|
|
95
|
+
* `runtime` plus `__row`/`__cell` markers that finalizeForRender() reads to emit a
|
|
96
|
+
* RESPONSIVE grid per breakpoint (it auto-collapses to fewer columns on tablet/mobile so
|
|
97
|
+
* the row never renders as cramped slivers).
|
|
98
|
+
*/
|
|
99
|
+
export function rowChildren(container, children, opts = {}) {
|
|
100
|
+
const cols = children.length || 1;
|
|
101
|
+
const colWidths = opts.colWidths && opts.colWidths.length === cols
|
|
102
|
+
? opts.colWidths
|
|
103
|
+
: Array.from({ length: cols }, () => ({ unit: "fr", value: 1 }));
|
|
104
|
+
const collapse = { ...ROW_COLLAPSE_DEFAULT, ...(opts.collapse || {}) };
|
|
105
|
+
const columnGap = opts.columnGap ?? 24;
|
|
106
|
+
const rowGap = opts.rowGap ?? 24;
|
|
107
|
+
const meta = { cols, count: children.length, collapse, columnGap, rowGap };
|
|
108
|
+
container.runtime = container.runtime || {};
|
|
109
|
+
container.runtime.config = {
|
|
110
|
+
...(container.runtime.config || {}),
|
|
111
|
+
grid: `${cols}x1`,
|
|
112
|
+
columns: colWidths,
|
|
113
|
+
rows: [ROW_PLACEHOLDER_ROW()],
|
|
114
|
+
columnGap,
|
|
115
|
+
rowGap,
|
|
116
|
+
heightUnit: "auto",
|
|
117
|
+
__row: meta,
|
|
118
|
+
};
|
|
119
|
+
children.forEach((child, i) => {
|
|
120
|
+
child.runtime = child.runtime || {};
|
|
121
|
+
child.runtime.config = {
|
|
122
|
+
...(child.runtime.config || {}),
|
|
123
|
+
columnStart: i + 1,
|
|
124
|
+
columnEnd: i + 2,
|
|
125
|
+
rowStart: 1,
|
|
126
|
+
rowEnd: 2,
|
|
127
|
+
constraintX: (child.runtime.config && child.runtime.config.constraintX) || ["centerLeft"],
|
|
128
|
+
constraintY: (child.runtime.config && child.runtime.config.constraintY) || ["top"],
|
|
129
|
+
loaded: true,
|
|
130
|
+
__cell: { index: i, ...meta },
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
container.children = children;
|
|
134
|
+
return container;
|
|
135
|
+
}
|
|
136
|
+
/** Build a standalone multi-column ROW container from child specs (each laid side by side).
|
|
137
|
+
* Used by the new_row tool; inside new_section pass `layout:"row"` on a container spec. */
|
|
138
|
+
export function buildRow(childSpecs = [], opts = {}) {
|
|
139
|
+
const container = buildElement("container", opts.containerOpts || {});
|
|
140
|
+
const children = childSpecs.map((spec) => buildFromSpec(spec));
|
|
141
|
+
return rowChildren(container, children, opts);
|
|
142
|
+
}
|
|
143
|
+
/** How many columns a row shows at a given breakpoint (clamped to its real column count). */
|
|
144
|
+
function colsForBp(meta, bp) {
|
|
145
|
+
const c = meta.collapse ? meta.collapse[bp] : null;
|
|
146
|
+
const k = c == null ? meta.cols : Math.min(c, meta.cols);
|
|
147
|
+
return Math.max(1, k);
|
|
148
|
+
}
|
|
87
149
|
/**
|
|
88
150
|
* Build a ready-to-place section from a list of child specs.
|
|
89
151
|
* Each spec: { type, opts?, children? } where children is a nested array of specs.
|
|
@@ -118,7 +180,19 @@ function buildFromSpec(spec) {
|
|
|
118
180
|
const node = buildElement(spec.type, spec.opts || {});
|
|
119
181
|
if (Array.isArray(spec.children) && spec.children.length) {
|
|
120
182
|
const kids = spec.children.map((c) => buildFromSpec(c));
|
|
121
|
-
|
|
183
|
+
// `layout:"row"` lays the children out side by side (responsive); default is a
|
|
184
|
+
// top-to-bottom vertical stack. rowGap/columnGap/colWidths/collapse tune the layout.
|
|
185
|
+
if (spec.layout === "row") {
|
|
186
|
+
rowChildren(node, kids, {
|
|
187
|
+
columnGap: spec.columnGap,
|
|
188
|
+
rowGap: spec.rowGap,
|
|
189
|
+
colWidths: spec.colWidths,
|
|
190
|
+
collapse: spec.collapse,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
stackChildren(node, kids, { rowGap: spec.rowGap });
|
|
195
|
+
}
|
|
122
196
|
}
|
|
123
197
|
return node;
|
|
124
198
|
}
|
|
@@ -193,9 +267,14 @@ function expandNodeToBreakpoints(node) {
|
|
|
193
267
|
const baseStyle = rt.style || {};
|
|
194
268
|
const baseConfig = { ...(rt.config || {}), loaded: true };
|
|
195
269
|
const isSection = node.type === "section";
|
|
270
|
+
const rowMeta = baseConfig.__row; // this node is a multi-column row container
|
|
271
|
+
const cellMeta = baseConfig.__cell; // this node is a cell inside a row
|
|
196
272
|
for (const [bp, [minW]] of Object.entries(BREAKPOINTS)) {
|
|
197
273
|
const style = clone(baseStyle);
|
|
198
274
|
const config = clone(baseConfig);
|
|
275
|
+
// Internal build-time markers never get persisted.
|
|
276
|
+
delete config.__row;
|
|
277
|
+
delete config.__cell;
|
|
199
278
|
if (isSection) {
|
|
200
279
|
const g = genGridByBp(minW);
|
|
201
280
|
const sectionRows = baseConfig.rows && baseConfig.rows.length ? clone(baseConfig.rows) : clone(g.rows);
|
|
@@ -204,6 +283,29 @@ function expandNodeToBreakpoints(node) {
|
|
|
204
283
|
config.grid = `3x${sectionRows.length}`;
|
|
205
284
|
config.heightUnit = config.heightUnit || "auto";
|
|
206
285
|
}
|
|
286
|
+
// A multi-column row collapses to fewer columns on smaller screens so cards never
|
|
287
|
+
// shrink to slivers: recompute the grid + this container's columns per breakpoint.
|
|
288
|
+
if (rowMeta) {
|
|
289
|
+
const k = colsForBp(rowMeta, bp);
|
|
290
|
+
const nrows = Math.ceil(rowMeta.count / k);
|
|
291
|
+
config.columns =
|
|
292
|
+
k === rowMeta.cols && Array.isArray(baseConfig.columns) && baseConfig.columns.length === k
|
|
293
|
+
? clone(baseConfig.columns)
|
|
294
|
+
: Array.from({ length: k }, () => ({ unit: "fr", value: 1 }));
|
|
295
|
+
config.rows = Array.from({ length: nrows }, () => ROW_PLACEHOLDER_ROW());
|
|
296
|
+
config.grid = `${k}x${nrows}`;
|
|
297
|
+
config.heightUnit = config.heightUnit || "auto";
|
|
298
|
+
}
|
|
299
|
+
// A cell repositions itself into the collapsed grid (wraps to a new row as needed).
|
|
300
|
+
if (cellMeta) {
|
|
301
|
+
const k = colsForBp(cellMeta, bp);
|
|
302
|
+
const c = cellMeta.index % k;
|
|
303
|
+
const r = Math.floor(cellMeta.index / k);
|
|
304
|
+
config.columnStart = c + 1;
|
|
305
|
+
config.columnEnd = c + 2;
|
|
306
|
+
config.rowStart = r + 1;
|
|
307
|
+
config.rowEnd = r + 2;
|
|
308
|
+
}
|
|
207
309
|
node[bp] = { style, config };
|
|
208
310
|
}
|
|
209
311
|
delete node.runtime;
|