@gudhub/ssg-web-components-library 1.0.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.
Files changed (230) hide show
  1. package/index.js +3 -0
  2. package/package.json +20 -0
  3. package/src/components/about-us-banner/about-us-banner-data.json +9 -0
  4. package/src/components/about-us-banner/about-us-banner.html +19 -0
  5. package/src/components/about-us-banner/about-us-banner.js +23 -0
  6. package/src/components/about-us-banner/about-us-banner.scss +59 -0
  7. package/src/components/about-us-banner/config.js +5 -0
  8. package/src/components/about-us-image-counter/about-us-image-counter-data.json +35 -0
  9. package/src/components/about-us-image-counter/about-us-image-counter.html +22 -0
  10. package/src/components/about-us-image-counter/about-us-image-counter.js +23 -0
  11. package/src/components/about-us-image-counter/about-us-image-counter.scss +44 -0
  12. package/src/components/about-us-image-counter/config.js +5 -0
  13. package/src/components/about-us-team-members/about-us-team-members-data.json +99 -0
  14. package/src/components/about-us-team-members/about-us-team-members.html +25 -0
  15. package/src/components/about-us-team-members/about-us-team-members.js +22 -0
  16. package/src/components/about-us-team-members/about-us-team-members.scss +71 -0
  17. package/src/components/about-us-team-members/config.js +5 -0
  18. package/src/components/animation-block/animation-block-data.json +40 -0
  19. package/src/components/animation-block/animation-block.html +37 -0
  20. package/src/components/animation-block/animation-block.js +23 -0
  21. package/src/components/animation-block/animation-block.scss +337 -0
  22. package/src/components/animation-block/config.js +5 -0
  23. package/src/components/banner-and-text/banner-and-text-data.json +24 -0
  24. package/src/components/banner-and-text/banner-and-text.html +30 -0
  25. package/src/components/banner-and-text/banner-and-text.js +25 -0
  26. package/src/components/banner-and-text/banner-and-text.scss +85 -0
  27. package/src/components/banner-and-text/config.js +5 -0
  28. package/src/components/blog/article/allArticles.json +96 -0
  29. package/src/components/blog/article/article-component.html +189 -0
  30. package/src/components/blog/article/article-component.js +340 -0
  31. package/src/components/blog/article/article-component.scss +776 -0
  32. package/src/components/blog/article/authors-object.json +125 -0
  33. package/src/components/blog/article/categories-object.json +47 -0
  34. package/src/components/blog/author-page/author-page.html +37 -0
  35. package/src/components/blog/author-page/author-page.js +113 -0
  36. package/src/components/blog/author-page/author-page.json +111 -0
  37. package/src/components/blog/author-page/author-page.scss +107 -0
  38. package/src/components/blog/authors-list/authors-list.html +40 -0
  39. package/src/components/blog/authors-list/authors-list.js +60 -0
  40. package/src/components/blog/authors-list/authors-list.json +132 -0
  41. package/src/components/blog/authors-list/authors-list.scss +171 -0
  42. package/src/components/blog/categories-list/categories-list.html +21 -0
  43. package/src/components/blog/categories-list/categories-list.js +26 -0
  44. package/src/components/blog/categories-list/categories-list.json +53 -0
  45. package/src/components/blog/categories-list/categories-list.scss +125 -0
  46. package/src/components/blog/comments/comments.html +89 -0
  47. package/src/components/blog/comments/comments.js +181 -0
  48. package/src/components/blog/comments/comments.json +130 -0
  49. package/src/components/blog/comments/comments.scss +324 -0
  50. package/src/components/blog/contents/contents.html +14 -0
  51. package/src/components/blog/contents/contents.js +63 -0
  52. package/src/components/blog/contents/contents.scss +157 -0
  53. package/src/components/blog/posts-template/articles.json +139 -0
  54. package/src/components/blog/posts-template/authors-object.json +61 -0
  55. package/src/components/blog/posts-template/categories.json +61 -0
  56. package/src/components/blog/posts-template/posts-template.html +239 -0
  57. package/src/components/blog/posts-template/posts-template.js +532 -0
  58. package/src/components/blog/posts-template/posts-template.scss +566 -0
  59. package/src/components/breadcrumbs/breadcrumbs-component.js +65 -0
  60. package/src/components/breadcrumbs/breadcrumbs.html +21 -0
  61. package/src/components/breadcrumbs/breadcrumbs.scss +118 -0
  62. package/src/components/breadcrumbs/config.js +5 -0
  63. package/src/components/button-component/button-component.html +3 -0
  64. package/src/components/button-component/button-component.js +39 -0
  65. package/src/components/button-component/button-component.readme.md +11 -0
  66. package/src/components/button-component/button-component.scss +34 -0
  67. package/src/components/button-component/config.js +5 -0
  68. package/src/components/category-banner/category-banner.html +7 -0
  69. package/src/components/category-banner/category-banner.js +44 -0
  70. package/src/components/category-banner/category-banner.scss +22 -0
  71. package/src/components/category-banner/config.js +5 -0
  72. package/src/components/contact-us-block/config.js +5 -0
  73. package/src/components/contact-us-block/contact-us-block.html +41 -0
  74. package/src/components/contact-us-block/contact-us-block.js +22 -0
  75. package/src/components/contact-us-block/contact-us-block.scss +59 -0
  76. package/src/components/cookies-popup/config.js +5 -0
  77. package/src/components/cookies-popup/cookies-popup.html +8 -0
  78. package/src/components/cookies-popup/cookies-popup.js +27 -0
  79. package/src/components/cookies-popup/cookies-popup.scss +68 -0
  80. package/src/components/counter-section/config.js +5 -0
  81. package/src/components/counter-section/counter-section-data.json +21 -0
  82. package/src/components/counter-section/counter-section.html +38 -0
  83. package/src/components/counter-section/counter-section.js +23 -0
  84. package/src/components/counter-section/counter-section.readme.md +19 -0
  85. package/src/components/counter-section/counter-section.scss +204 -0
  86. package/src/components/counter-section-with-text/config.js +5 -0
  87. package/src/components/counter-section-with-text/counter-section-with-text-data.json +21 -0
  88. package/src/components/counter-section-with-text/counter-section-with-text.html +46 -0
  89. package/src/components/counter-section-with-text/counter-section-with-text.js +23 -0
  90. package/src/components/counter-section-with-text/counter-section-with-text.readme.md +19 -0
  91. package/src/components/counter-section-with-text/counter-section-with-text.scss +164 -0
  92. package/src/components/crm-services-banner/config.js +5 -0
  93. package/src/components/crm-services-banner/crm-services-banner-data.json +20 -0
  94. package/src/components/crm-services-banner/crm-services-banner.html +28 -0
  95. package/src/components/crm-services-banner/crm-services-banner.js +25 -0
  96. package/src/components/crm-services-banner/crm-services-banner.scss +57 -0
  97. package/src/components/edit-mode/config.js +5 -0
  98. package/src/components/edit-mode/edit-mode.html +4 -0
  99. package/src/components/edit-mode/edit-mode.js +23 -0
  100. package/src/components/edit-mode/edit-mode.scss +69 -0
  101. package/src/components/faq/config.js +5 -0
  102. package/src/components/faq/faq.html +20 -0
  103. package/src/components/faq/faq.js +40 -0
  104. package/src/components/faq/faq.scss +80 -0
  105. package/src/components/footer/config.js +5 -0
  106. package/src/components/footer/footer.html +74 -0
  107. package/src/components/footer/footer.js +21 -0
  108. package/src/components/footer/footer.scss +356 -0
  109. package/src/components/footer/pages-object.json +58 -0
  110. package/src/components/fullscreen-image-and-text/config.js +5 -0
  111. package/src/components/fullscreen-image-and-text/fullscreen-image-and-text.html +42 -0
  112. package/src/components/fullscreen-image-and-text/fullscreen-image-and-text.js +29 -0
  113. package/src/components/fullscreen-image-and-text/fullscreen-image-and-text.scss +192 -0
  114. package/src/components/get-in-touch-block/config.js +5 -0
  115. package/src/components/get-in-touch-block/get-in-touch-block-data.json +4 -0
  116. package/src/components/get-in-touch-block/get-in-touch-block.html +11 -0
  117. package/src/components/get-in-touch-block/get-in-touch-block.js +22 -0
  118. package/src/components/get-in-touch-block/get-in-touch-block.scss +12 -0
  119. package/src/components/get-in-touch-form/config.js +5 -0
  120. package/src/components/get-in-touch-form/get-in-touch-form-data.json +114 -0
  121. package/src/components/get-in-touch-form/get-in-touch-form.html +35 -0
  122. package/src/components/get-in-touch-form/get-in-touch-form.js +115 -0
  123. package/src/components/get-in-touch-form/get-in-touch-form.readme.md +45 -0
  124. package/src/components/get-in-touch-form/get-in-touch-form.scss +334 -0
  125. package/src/components/get-in-touch-form/sendEmail.js +161 -0
  126. package/src/components/grid/config.js +5 -0
  127. package/src/components/grid/grid.html +51 -0
  128. package/src/components/grid/grid.js +115 -0
  129. package/src/components/grid/grid.scss +566 -0
  130. package/src/components/grid-component/config.js +5 -0
  131. package/src/components/grid-component/grid-component-data.json +115 -0
  132. package/src/components/grid-component/grid-component.html +52 -0
  133. package/src/components/grid-component/grid-component.js +40 -0
  134. package/src/components/grid-component/grid-component.readme.md +32 -0
  135. package/src/components/grid-component/grid-component.scss +199 -0
  136. package/src/components/header/config.js +5 -0
  137. package/src/components/header/header.html +60 -0
  138. package/src/components/header/header.js +55 -0
  139. package/src/components/header/header.scss +556 -0
  140. package/src/components/homepage-banner/config.js +5 -0
  141. package/src/components/homepage-banner/homepage-banner.html +1443 -0
  142. package/src/components/homepage-banner/homepage-banner.js +23 -0
  143. package/src/components/homepage-banner/homepage-banner.scss +147 -0
  144. package/src/components/image-component/config.js +5 -0
  145. package/src/components/image-component/image-component.html +25 -0
  146. package/src/components/image-component/image-component.js +107 -0
  147. package/src/components/list-text-and-media/config.js +5 -0
  148. package/src/components/list-text-and-media/list-text-and-media-data.json +70 -0
  149. package/src/components/list-text-and-media/list-text-and-media.html +38 -0
  150. package/src/components/list-text-and-media/list-text-and-media.js +22 -0
  151. package/src/components/list-text-and-media/list-text-and-media.readme.md +30 -0
  152. package/src/components/list-text-and-media/list-text-and-media.scss +156 -0
  153. package/src/components/media-and-accordion/config.js +5 -0
  154. package/src/components/media-and-accordion/media-and-accordion-data.json +84 -0
  155. package/src/components/media-and-accordion/media-and-accordion.html +37 -0
  156. package/src/components/media-and-accordion/media-and-accordion.js +55 -0
  157. package/src/components/media-and-accordion/media-and-accordion.scss +170 -0
  158. package/src/components/media-and-list-of-text/config.js +5 -0
  159. package/src/components/media-and-list-of-text/media-and-list-of-text-data.json +16 -0
  160. package/src/components/media-and-list-of-text/media-and-list-of-text.html +32 -0
  161. package/src/components/media-and-list-of-text/media-and-list-of-text.js +24 -0
  162. package/src/components/media-and-list-of-text/media-and-list-of-text.readme.md +26 -0
  163. package/src/components/media-and-list-of-text/media-and-list-of-text.scss +102 -0
  164. package/src/components/media-and-text/config.js +5 -0
  165. package/src/components/media-and-text/media-and-text-data.json +20 -0
  166. package/src/components/media-and-text/media-and-text.html +26 -0
  167. package/src/components/media-and-text/media-and-text.js +26 -0
  168. package/src/components/media-and-text/media-and-text.scss +51 -0
  169. package/src/components/meta/articles.json +95 -0
  170. package/src/components/meta/author-schema.js +71 -0
  171. package/src/components/meta/authors.json +108 -0
  172. package/src/components/meta/blog-schema.js +93 -0
  173. package/src/components/meta/canonical.js +74 -0
  174. package/src/components/meta/config.js +40 -0
  175. package/src/components/meta/meta-index.js +14 -0
  176. package/src/components/meta/meta-tag.js +168 -0
  177. package/src/components/meta/organization-schema.js +50 -0
  178. package/src/components/meta/service-schema.js +76 -0
  179. package/src/components/meta/title-tag.js +64 -0
  180. package/src/components/overflow-cards/config.js +5 -0
  181. package/src/components/overflow-cards/overflow-cards-data.json +33 -0
  182. package/src/components/overflow-cards/overflow-cards.html +33 -0
  183. package/src/components/overflow-cards/overflow-cards.js +28 -0
  184. package/src/components/overflow-cards/overflow-cards.scss +112 -0
  185. package/src/components/popup/config.js +5 -0
  186. package/src/components/popup/popup.html +10 -0
  187. package/src/components/popup/popup.js +66 -0
  188. package/src/components/popup/popup.readme.md +13 -0
  189. package/src/components/popup/popup.scss +76 -0
  190. package/src/components/prices-cards/config.js +5 -0
  191. package/src/components/prices-cards/prices-cards-data.json +90 -0
  192. package/src/components/prices-cards/prices-cards.html +35 -0
  193. package/src/components/prices-cards/prices-cards.js +23 -0
  194. package/src/components/prices-cards/prices-cards.readme.md +48 -0
  195. package/src/components/prices-cards/prices-cards.scss +206 -0
  196. package/src/components/recent-posts/author-object.json +53 -0
  197. package/src/components/recent-posts/config.js +5 -0
  198. package/src/components/recent-posts/recent-posts.html +85 -0
  199. package/src/components/recent-posts/recent-posts.js +89 -0
  200. package/src/components/recent-posts/recent-posts.json +258 -0
  201. package/src/components/recent-posts/recent-posts.scss +274 -0
  202. package/src/components/reviews-slider/config.js +5 -0
  203. package/src/components/reviews-slider/reviews-slider-data.json +30 -0
  204. package/src/components/reviews-slider/reviews-slider.html +48 -0
  205. package/src/components/reviews-slider/reviews-slider.js +86 -0
  206. package/src/components/reviews-slider/reviews-slider.scss +92 -0
  207. package/src/components/service-counter/config.js +5 -0
  208. package/src/components/service-counter/service-counter-data.json +24 -0
  209. package/src/components/service-counter/service-counter.html +19 -0
  210. package/src/components/service-counter/service-counter.js +23 -0
  211. package/src/components/service-counter/service-counter.scss +171 -0
  212. package/src/components/service-image-counter/config.js +5 -0
  213. package/src/components/service-image-counter/service-image-counter-data.json +52 -0
  214. package/src/components/service-image-counter/service-image-counter.html +30 -0
  215. package/src/components/service-image-counter/service-image-counter.js +23 -0
  216. package/src/components/service-image-counter/service-image-counter.scss +114 -0
  217. package/src/components/tabs/config.js +5 -0
  218. package/src/components/tabs/tabs-component.js +45 -0
  219. package/src/components/tabs/tabs.html +28 -0
  220. package/src/components/tabs/tabs.scss +399 -0
  221. package/src/components/text-only/config.js +5 -0
  222. package/src/components/text-only/text-only-data.json +4 -0
  223. package/src/components/text-only/text-only.html +8 -0
  224. package/src/components/text-only/text-only.js +20 -0
  225. package/src/components/text-only/text-only.scss +21 -0
  226. package/src/components/top-banner/config.js +5 -0
  227. package/src/components/top-banner/top-banner.html +22 -0
  228. package/src/components/top-banner/top-banner.js +50 -0
  229. package/src/components/top-banner/top-banner.scss +132 -0
  230. package/src/config.js +38 -0
@@ -0,0 +1,168 @@
1
+ import generalInfo from '/src/general-info.json';
2
+
3
+ class MetaTag extends GHComponent {
4
+ /**
5
+ * type = title / ddescription / meta_image_src - every value generate different meta tag
6
+ * og - generate open graph meta tag with type you set
7
+ * twitter - generate meta tag of twitter card with type you set
8
+ * data-twitter-name - name of your twitter account (@Template)
9
+ * data-chapter - chapter, default - pages
10
+ * data-appId - app id of application with this page
11
+ * data-itemId - item id of item with this page
12
+ */
13
+ constructor() {
14
+ super();
15
+ }
16
+
17
+ async onServerRender() {
18
+ this.type = this.getAttribute('type');
19
+ this.og = this.hasAttribute('og') ? true : false;
20
+ this.twitter = this.hasAttribute('twitter') ? true : false;
21
+ this.twitterName = this.hasAttribute('data-twitter-name') ? this.getAttribute('data-twitter-name') : false;
22
+ const appId = this.hasAttribute('data-appId') ? this.getAttribute('data-appId') : false;
23
+ const itemId = this.hasAttribute('data-itemId') ? this.getAttribute('data-itemId') : false;
24
+ const chapter = this.hasAttribute('data-chapter') ? this.getAttribute('data-chapter') : 'pages';
25
+
26
+ if (appId && itemId) {
27
+ this.addTag(appId, itemId, false, chapter);
28
+ } else {
29
+ if (chapter == 'blog' && !itemId) {
30
+ const url = new URL(window.location.href);
31
+ const category = url.searchParams.get('category');
32
+ const path = url.searchParams.get('path');
33
+ if (path.includes('/page/')) {
34
+ let slug = `/blog/${category}/`;
35
+ await this.addTag(appId, false, slug, chapter);
36
+ } else {
37
+ let ids = await super.findIds(chapter);
38
+ await this.addTag(ids.appId, ids.itemId, false, chapter);
39
+ }
40
+ } else {
41
+ let ids = await super.findIds(chapter);
42
+ await this.addTag(ids.appId, ids.itemId, false, chapter);
43
+ }
44
+ }
45
+ }
46
+ async addTag (appId, itemId, slug, chapter) {
47
+ const app = await gudhub.getApp(appId);
48
+ const items = app.items_list;
49
+ let item;
50
+ let fieldId;
51
+ let value;
52
+ if (!slug) {
53
+ item = items.find(findedItem => findedItem.item_id == itemId);
54
+ } else {
55
+ for (let findedItem in items) {
56
+
57
+ let iterationItem = items[findedItem].fields.find(field => field.field_value == slug)
58
+ if (iterationItem) {
59
+ item = items[findedItem];
60
+ }
61
+ }
62
+
63
+ }
64
+
65
+ fieldId = app.field_list.find(findedField => findedField.name_space === this.type);
66
+ fieldId = fieldId.field_id;
67
+ value = item.fields.find(findedField => findedField.field_id == fieldId).field_value;
68
+
69
+ value = isNaN(value) ? value : await this.getContent(`https://gudhub.com/userdata/${window.constants.chapters[chapter].app_id}/${value}.html`);
70
+
71
+ if (this.og) {
72
+ if (this.type != 'meta_image_src') {
73
+ const meta = document.createElement('meta');
74
+ let type = this.type;
75
+ const name = 'og:' + type;
76
+ meta.setAttribute('property', name);
77
+ meta.setAttribute('content', value);
78
+ document.querySelector('head').prepend(meta);
79
+ }
80
+ if (this.type == 'title') {
81
+ const metaSiteName = document.createElement('meta');
82
+ const name = 'og:site_name';
83
+ metaSiteName.setAttribute('property', name);
84
+ metaSiteName.setAttribute('content', generalInfo.name);
85
+ document.querySelector('head').prepend(metaSiteName);
86
+ }
87
+ if (this.type == 'meta_image_src') {
88
+ const metaSiteImage = document.createElement('meta');
89
+ const name = 'og:image';
90
+ metaSiteImage.setAttribute('property', name);
91
+ metaSiteImage.setAttribute('content', `${window.MODE === 'production' ? 'https' : 'http'}://${window.constants.website}${value}`);
92
+ document.querySelector('head').prepend(metaSiteImage);
93
+ }
94
+ } else if (this.twitter) {
95
+ if (this.type != 'meta_image_src') {
96
+ const meta = document.createElement('meta');
97
+ let type = this.type;
98
+ const name = 'twitter:' + type;
99
+ meta.setAttribute('name', name);
100
+ meta.setAttribute('content', value);
101
+ document.querySelector('head').prepend(meta);
102
+ }
103
+
104
+ if (this.type == 'title') {
105
+ const metaCard = document.createElement('meta');
106
+ metaCard.setAttribute('name', 'twitter:card');
107
+ metaCard.setAttribute('content', 'summary_large_image');
108
+
109
+ document.querySelector('head').prepend(metaCard);
110
+
111
+ const metaSite = document.createElement('meta');
112
+ metaSite.setAttribute('name', 'twitter:site');
113
+ metaSite.setAttribute('content', this.twitterName);
114
+
115
+ document.querySelector('head').prepend(metaSite);
116
+ }
117
+
118
+
119
+ if (this.type == 'meta_image_src') {
120
+ const metaSiteImage = document.createElement('meta');
121
+ const name = 'twitter:image';
122
+ metaSiteImage.setAttribute('name', name);
123
+ metaSiteImage.setAttribute('content', `${window.MODE === 'production' ? 'https' : 'http'}://${window.constants.website}${value}`);
124
+ document.querySelector('head').prepend(metaSiteImage);
125
+ }
126
+ } else {
127
+ const meta = document.createElement('meta');
128
+ let name;
129
+ if (this.type == "title") {
130
+ name = "title"
131
+ } else if (this.type == "meta_image_src") {
132
+ name = "image"
133
+ } else {
134
+ name = this.type
135
+ }
136
+ meta.setAttribute('name', name);
137
+ meta.setAttribute('content', value);
138
+ document.querySelector('head').prepend(meta);
139
+ }
140
+ if (!document.querySelector('[property="og:type"]')) {
141
+ const metaWebsite = document.createElement('meta');
142
+ metaWebsite.setAttribute('property', 'og:type');
143
+ metaWebsite.setAttribute('content', 'webiste');
144
+ document.querySelector('head').prepend(metaWebsite);
145
+ }
146
+
147
+ if (!document.querySelector('[property="og:locale"]')) {
148
+ const metaLocale = document.createElement('meta');
149
+ metaLocale.setAttribute('property', 'og:locale');
150
+ metaLocale.setAttribute('content', 'en');
151
+ document.querySelector('head').prepend(metaLocale);
152
+ }
153
+
154
+ this.remove();
155
+ }
156
+
157
+ getContent(link) {
158
+ return new Promise(async (resolve) => {
159
+ const response = await fetch(link);
160
+ const content = await response.text();
161
+ const div = document.createElement('div');
162
+ div.insertAdjacentHTML('beforeend', content);
163
+ resolve(div.innerText);
164
+ });
165
+ }
166
+ }
167
+
168
+ window.customElements.define('meta-tag', MetaTag);
@@ -0,0 +1,50 @@
1
+ import generalInfo from '/src/general-info.json';
2
+ class OrganizationSchema extends GHComponent {
3
+ constructor() {
4
+ super();
5
+ }
6
+
7
+ async onServerRender() {
8
+ const schema = {
9
+ "@context": "https://schema.org",
10
+ "@type": "Organization",
11
+ "name": generalInfo.name,
12
+ "legalName": generalInfo.legalName,
13
+ "url": `${window.MODE === 'production' ? 'https' : 'http'}://${window.constants.website}`,
14
+ "logo": `${window.MODE === 'production' ? 'https' : 'http'}://${window.constants.website}/assets/images/logo.svg`,
15
+ "foundingDate": generalInfo.foundingDate,
16
+ "founders": [
17
+ {
18
+ "@type": "Person",
19
+ "name": generalInfo.founders
20
+ }
21
+ ],
22
+ "address": {
23
+ "@type": "PostalAddress",
24
+ "streetAddress": generalInfo.separatedAddress.streetAddress,
25
+ "addressLocality": generalInfo.separatedAddress.addressLocality,
26
+ "addressRegion": generalInfo.separatedAddress.addressRegion,
27
+ "postalCode": generalInfo.separatedAddress.postalCode,
28
+ "addressCountry": generalInfo.separatedAddress.addressCountry
29
+ },
30
+ "contactPoint": {
31
+ "@type": "ContactPoint",
32
+ "contactType": "customer support",
33
+ "telephone": `[${generalInfo.phone}]`,
34
+ "email": generalInfo.email
35
+ },
36
+ "sameAs": [generalInfo.socLinks.linkedin, generalInfo.socLinks.facebook, generalInfo.socLinks.instagram, generalInfo.socLinks.twitter]
37
+ }
38
+
39
+ if (!document.head.querySelector('#organizationSchema')) {
40
+
41
+ document.head.innerHTML += `
42
+ <script id="organizationSchema" type="application/ld+json">${JSON.stringify(schema)}</script>
43
+ `;
44
+
45
+ }
46
+ this.remove();
47
+ }
48
+ }
49
+
50
+ window.customElements.define('organization-schema', OrganizationSchema);
@@ -0,0 +1,76 @@
1
+ import generalInfo from '/src/general-info.json';
2
+ class ServiceSchema extends GHComponent {
3
+ /**
4
+ * data-chapter - chapter, default - pages
5
+ */
6
+ constructor() {
7
+ super();
8
+ }
9
+
10
+ async onServerRender() {
11
+ const chapter = this.hasAttribute('data-chapter') ? this.getAttribute('data-chapter') : 'pages';
12
+
13
+ let ids = await super.findIds(chapter);
14
+ const app = await gudhub.getApp(ids.appId);
15
+ const items = app.items_list;
16
+ let item = items.find(findedItem => findedItem.item_id == ids.itemId);
17
+ const serviceName = item.fields.find(field => field.field_id == window.constants.chapters[chapter].heading_field_id).field_value;
18
+ const serviceDescription = item.fields.find(field => field.field_id == window.constants.chapters[chapter].description_field_id).field_value;
19
+ const serviceSlug = item.fields.find(field => field.field_id == window.constants.chapters[chapter].slug_field_id).field_value;
20
+ const serviceImage = item.fields.find(field => field.field_id == window.constants.chapters[chapter].image_field_id).field_value;
21
+ const schema = {
22
+ "@context": "https://schema.org",
23
+ "@type": "Service",
24
+ "name": serviceName,
25
+ "description": serviceDescription,
26
+ "url": `${window.MODE === 'production' ? 'https' : 'http'}://${window.constants.website}${serviceSlug}`,
27
+ "provider": {
28
+ "@type": "Organization",
29
+ "name": generalInfo.name
30
+ },
31
+ "serviceType": "IT Development Services",
32
+ "areaServed": [
33
+ {
34
+ "@type": "Place",
35
+ "address": {
36
+ "@type": "PostalAddress",
37
+ "streetAddress": generalInfo.separatedAddress.streetAddress,
38
+ "addressLocality": generalInfo.separatedAddress.addressLocality,
39
+ "addressRegion": generalInfo.separatedAddress.addressRegion,
40
+ "postalCode": generalInfo.separatedAddress.postalCode,
41
+ "addressCountry": generalInfo.separatedAddress.addressCountry
42
+ }
43
+ }
44
+ ],
45
+ "hoursAvailable": {
46
+ "@type": "OpeningHoursSpecification",
47
+ "opens": "09:00",
48
+ "closes": "18:00",
49
+ "dayOfWeek": [
50
+ "Monday",
51
+ "Tuesday",
52
+ "Wednesday",
53
+ "Thursday",
54
+ "Friday"
55
+ ]
56
+ },
57
+ "image": {
58
+ "@type": "ImageObject",
59
+ "url": `${window.MODE === 'production' ? 'https' : 'http'}://${window.constants.website}${serviceImage}`,
60
+ "width": "800",
61
+ "height": "600"
62
+ }
63
+ };
64
+
65
+ if (!document.head.querySelector('#serviceSchema')) {
66
+
67
+ document.head.innerHTML += `
68
+ <script id="serviceSchema" type="application/ld+json">${JSON.stringify(schema)}</script>
69
+ `;
70
+
71
+ }
72
+ this.remove();
73
+ }
74
+ }
75
+
76
+ window.customElements.define('service-schema', ServiceSchema);
@@ -0,0 +1,64 @@
1
+ class TitleTag extends GHComponent {
2
+ /**
3
+ * data-chapter - chapter, default - pages
4
+ * data-appId - app id of application with this page
5
+ * data-itemId - item id of item with this page
6
+ */
7
+ constructor() {
8
+ super();
9
+ }
10
+
11
+ async onServerRender() {
12
+ const appId = this.hasAttribute('data-appId') ? this.getAttribute('data-appId') : false;
13
+ const itemId = this.hasAttribute('data-itemId') ? this.getAttribute('data-itemId') : false;
14
+ if (appId && itemId) {
15
+ this.findTitle(appId, itemId, false);
16
+ } else {
17
+ const chapter = this.hasAttribute('data-chapter') ? this.getAttribute('data-chapter') : 'pages';
18
+ if (chapter == 'blog' && !itemId) {
19
+ const url = new URL(window.location.href);
20
+ const category = url.searchParams.get('category');
21
+ const path = url.searchParams.get('path');
22
+ if (path.includes('/page/')) {
23
+ let slug = `/blog/${category}/`;
24
+ await this.findTitle(appId, false, slug);
25
+ } else {
26
+ let ids = await super.findIds(chapter);
27
+ await this.findTitle(ids.appId, ids.itemId, false);
28
+ }
29
+ } else {
30
+ let ids = await super.findIds(chapter);
31
+ await this.findTitle(ids.appId, ids.itemId, false);
32
+ }
33
+ }
34
+ }
35
+ async findTitle (appId, itemId, slug) {
36
+ const app = await gudhub.getApp(appId);
37
+ const items = app.items_list;
38
+
39
+ let item;
40
+ let fieldId;
41
+ let value;
42
+ if (!slug) {
43
+ item = items.find(findedItem => findedItem.item_id == itemId);
44
+ } else {
45
+ items.forEach(findedItem => {
46
+ let iterationItem = findedItem.fields.find(field => field.field_value == slug)
47
+ if (iterationItem) {
48
+ item = findedItem;
49
+ }
50
+ });
51
+ }
52
+ fieldId = app.field_list.find(findedField => findedField.name_space === 'title').field_id;
53
+ value = item.fields.find(findedField => findedField.field_id == fieldId).field_value;
54
+
55
+
56
+ const title = document.createElement('title');
57
+ title.innerText = value;
58
+
59
+ document.querySelector('head').appendChild(title);
60
+ this.remove();
61
+ }
62
+ }
63
+
64
+ window.customElements.define('title-tag', TitleTag);
@@ -0,0 +1,5 @@
1
+ export const overflowCards = {
2
+ tag: 'overflow-cards',
3
+ src: '@gudhub/ssg-web-component-library/src/components/overflow-cards/overflow-cards.js',
4
+ serverOnly: false
5
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "title": "Використання GudHub CRM Системи для Бізнесу",
3
+ "subtitle": "Разом з CRM платформою для бізнесу, компанії успішно збільшили кількість замовлень та клієнтів і вивели свій бізнез на новий рівень!",
4
+ "cards": [
5
+ {
6
+ "title": "Компанія Atlasiko подвоїла кількість замовлень",
7
+ "text": "Завдяки зручній системі комунікації та ряду запропонованих інструментів, ІТ компанія отримує більшу кількість замовлень, тим самим сприяючи росту та розвитку бізнесу",
8
+ "image": {
9
+ "src": "/assets/images/media-icons.jpg",
10
+ "alt": "Media Icons",
11
+ "title": "Media Icons"
12
+ }
13
+ },
14
+ {
15
+ "title": "х3 нових клієнтів в Applet3D",
16
+ "text": "За допомогою запуску кампаній та розсилки електронних листів, кількість клієнтів на послуги 3D візуалізації та анімації архітектури в Applet3D збільшилися втричі.",
17
+ "image": {
18
+ "src": "/assets/images/media-icons-2.jpg",
19
+ "alt": "Media Icons",
20
+ "title": "Media Icons"
21
+ }
22
+ },
23
+ {
24
+ "title": "EasyStoneShop досягла точнішого прогнозування продажів",
25
+ "text": "Компанія може передбачити кількість продажів за місяць і сформувати сценарії частоти замовлень.",
26
+ "image": {
27
+ "src": "/assets/images/media-icons-3.jpg",
28
+ "alt": "Media Icons",
29
+ "title": "Media Icons"
30
+ }
31
+ }
32
+ ]
33
+ }
@@ -0,0 +1,33 @@
1
+ <section class="overflow-cards">
2
+ <div class="container">
3
+ <div class="top">
4
+ <div class="top_left">
5
+ <h2 gh-id="${ghId}.title"> TITLE </h2>
6
+
7
+ ${jsonData.subtitle ? `
8
+ <p class="subtitle" gh-id="${ghId}.subtitle">
9
+ SUBTITLE
10
+ </p>
11
+ ` : ''}
12
+ </div>
13
+ <div class="top_right">
14
+ ${button ? `
15
+ <button-component data-popup-id="${button.popupId}" data-placement="${button.placement}">${button.text}</button-component>
16
+ ` : ''}
17
+ </div>
18
+ </div>
19
+ <div class="flex-wrapper">
20
+ ${cards.reduce((acc, card, index) => {
21
+ return acc + `
22
+ <div class="cards">
23
+ <h3 gh-id="${ghId}.cards.${index}.title"></h3>
24
+ <div class="text">
25
+ <p gh-id="${ghId}.cards.${index}.text"></p>
26
+ </div>
27
+ <image-component src="${card.image.src}" alt="${card.image.alt}" title="${card.image.title}" lazyload width="330" height="274"></image-component>
28
+ </div>
29
+ `
30
+ }, '')}
31
+ </div>
32
+ </div>
33
+ </section>
@@ -0,0 +1,28 @@
1
+ import html from './overflow-cards.html';
2
+ import './overflow-cards.scss';
3
+ import jsonTemplate from './overflow-cards-data.json';
4
+
5
+ class OverflowCards extends GHComponent {
6
+
7
+ constructor() {
8
+ super();
9
+ super.setDefaultData(jsonTemplate);
10
+ this.ghId = this.getAttribute('data-gh-id') || null;
11
+ }
12
+
13
+ async onServerRender() {
14
+ this.ghId = this.getAttribute('data-gh-id') || null;
15
+ this.subtitle = this.hasAttribute('data-subtitle') ? this.getAttribute('data-subtitle') : true;
16
+
17
+ const json = await super.getGhData(this.ghId);
18
+
19
+ this.jsonData = json;
20
+
21
+ this.cards = json.cards;
22
+ this.button = json.button ? json.button : {"text": "Спробувати Безкоштовно", "class": 'btn'};
23
+
24
+ super.render(html);
25
+ }
26
+ }
27
+
28
+ window.customElements.define('overflow-cards', OverflowCards);
@@ -0,0 +1,112 @@
1
+ overflow-cards {
2
+ background: var(--primary-bg-color);
3
+ .top {
4
+ display: flex;
5
+ justify-content: space-between;
6
+ align-items: center;
7
+ gap: 30px;
8
+ margin-bottom: 30px;
9
+ }
10
+ h2 {
11
+ text-align: left;
12
+ max-width: 804px;
13
+ }
14
+ .subtitle {
15
+ max-width: 804px;
16
+ margin-bottom: 0 !important;
17
+ }
18
+ .btn {
19
+ white-space: nowrap;
20
+ }
21
+ .flex-wrapper {
22
+ position: relative;
23
+ bottom: -100px;
24
+ margin-top: -100px;
25
+ gap: 20px;
26
+ flex-wrap: wrap;
27
+ .cards {
28
+ width: calc(33% - 13px);
29
+ border-radius: var(--block-primary-border-radius);
30
+ background: var(--block-primary-bg-color);
31
+ padding: 30px;
32
+ display: flex;
33
+ flex-direction: column;
34
+ gap: 20px;
35
+ h3 {
36
+ color: var(--block-primary-h-color);
37
+ margin-bottom: 0;
38
+ }
39
+ .text {
40
+ color: var(--block-primary-text-color);
41
+ }
42
+ img {
43
+ width: 100%;
44
+ height: auto;
45
+ border-radius: var(--block-primary-border-radius);
46
+ background-color: var(--image-bg-color);
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ @media screen and (max-width: 1050px) {
53
+ overflow-cards .flex-wrapper .cards {
54
+ padding: 20px;
55
+ }
56
+ }
57
+ @media screen and (min-width: 1050px) {
58
+ overflow-cards {
59
+ section {
60
+ padding-bottom: 0;
61
+ }
62
+ }
63
+ }
64
+ @media screen and (max-width: 1050px) {
65
+ overflow-cards .flex-wrapper {
66
+ bottom: 0;
67
+ margin-top: 0;
68
+ .cards {
69
+ width: calc(50% - 10px);
70
+ }
71
+ }
72
+ }
73
+ @media screen and (max-width: 950px) {
74
+ overflow-cards .top {
75
+ flex-direction: column;
76
+ }
77
+ }
78
+
79
+ @media screen and (max-width: 600px) {
80
+ overflow-cards {
81
+ h2 {
82
+ text-align: center;
83
+ }
84
+ .subtitle {
85
+ text-align: center;
86
+ }
87
+ .flex-wrapper {
88
+ justify-content: center;
89
+ .cards {
90
+ width: 100%;
91
+ max-width: 400px;
92
+ text-align: center;
93
+ }
94
+ }
95
+ }
96
+ }
97
+ @media screen and (max-width: 450px) {
98
+ overflow-cards {
99
+ h2 {
100
+ text-align: left;
101
+ }
102
+ .subtitle {
103
+ text-align: left;
104
+ }
105
+ .flex-wrapper {
106
+ .cards {
107
+ text-align: left;
108
+
109
+ }
110
+ }
111
+ }
112
+ }
@@ -0,0 +1,5 @@
1
+ export const popupContainer = {
2
+ tag: 'popup-container',
3
+ src: '@gudhub/ssg-web-component-library/src/components/popup/popup.js',
4
+ serverOnly: false
5
+ }
@@ -0,0 +1,10 @@
1
+ <div class="background_shadow" onclick="backgroundClosePopup()">
2
+ <div class="popup">
3
+ <div class="popup_top">
4
+ <div class="close" onclick="closePopup()">
5
+ <svg xmlns="http://www.w3.org/2000/svg" width="29" height="30" viewBox="0 0 29 30" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M6.85786 21.1421L21 7L22.4142 8.41421L8.27208 22.5564L6.85786 21.1421Z" fill="#1B1B1D"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M8.85786 6.85786L23 21L21.5858 22.4142L7.44365 8.27208L8.85786 6.85786Z" fill="#1B1B1D"></path></svg>
6
+ </div>
7
+ </div>
8
+ <div class="child-container"></div>
9
+ </div>
10
+ </div>
@@ -0,0 +1,66 @@
1
+ import html from './popup.html';
2
+ import './popup.scss';
3
+
4
+ class Popup extends GHComponent {
5
+
6
+ constructor() {
7
+ super();
8
+ this.popupId = this.getAttribute('data-popup-id');
9
+ }
10
+
11
+ async onServerRender() {
12
+ const child = this.innerHTML;
13
+ super.render(html);
14
+ const childContainer = this.getChildContainer();
15
+ if (childContainer && child) {
16
+ childContainer.innerHTML = child;
17
+ }
18
+ }
19
+
20
+ onClientReady() {
21
+ this.renderChild();
22
+ if (this.hasAttribute('data-autostart')) {
23
+ const delay = Number(this.getAttribute('data-autostart'));
24
+ if (delay) {
25
+ setTimeout(() => this.openPopup(), delay);
26
+ }
27
+ }
28
+ window.addEventListener('open-popup', (e) => {
29
+ if (this.popupId === e.detail.popupId) {
30
+ if (this.child && this.child.tagName.toLowerCase() === 'get-in-touch-form') {
31
+ this.child.placement = e.detail.placement ? e.detail.placement : 'no-placement-attribute';
32
+ }
33
+ this.openPopup();
34
+ }
35
+ });
36
+ }
37
+
38
+ getChildContainer() {
39
+ return this.getElementsByClassName('child-container')[0];
40
+ }
41
+
42
+ renderChild() {
43
+ const childContainer = this.getChildContainer();
44
+ this.child = childContainer.children[0];
45
+ if (this.child) {
46
+ this.child.clientRender();
47
+ }
48
+ }
49
+
50
+ backgroundClosePopup() {
51
+ if (event.target.className == 'background_shadow') {
52
+ this.closePopup();
53
+ }
54
+ }
55
+
56
+ openPopup() {
57
+ this.classList.add('active');
58
+ }
59
+
60
+ closePopup() {
61
+ this.classList.remove('active');
62
+ this.child.onParentPopupClose();
63
+ }
64
+ }
65
+
66
+ window.customElements.define('popup-container', Popup);
@@ -0,0 +1,13 @@
1
+
2
+ # Usage:
3
+ The component that should be in the popup is written inside the component: "<popup-container> <YOUR-COMPONENT> </popup-container>".
4
+ Also, on the user's client, the popup calls the "clientRender()" method, if it is defined in your component that is in the popup, it will be applied.
5
+
6
+ # Data-attributes:
7
+ data-popup-id="popup-id": there can be several popups on the page, so that the popup understands what exactly it should open with the id attribute. When the "open-popup" event si dispatched, the popup checks whether "e.detail.popupId" matches the id in the popup attribute.
8
+
9
+ data-autostart="time in milliseconds": popup will open itself after delay
10
+
11
+ data-no-bg-shadow: shadowed background will not appear
12
+
13
+ data-position="bottom-right": popup will be positioned in right bottom corner