├── .github
└── workflows
│ └── nodejs.yml
├── assets
├── css
│ ├── admin.css
│ ├── admin.css.map
│ ├── admin.scss
│ ├── calendar.css
│ ├── elements.css
│ ├── elements.css.map
│ ├── elements.scss
│ ├── popup-builder.css
│ ├── popup-builder.css.map
│ ├── popup-builder.scss
│ ├── popups.css
│ ├── popups.css.map
│ └── popups.scss
├── img
│ ├── default
│ │ ├── cafe.png
│ │ ├── city-day.png
│ │ ├── city-night.png
│ │ ├── clothes.png
│ │ ├── man-blue.png
│ │ ├── man-thumbs-up.png
│ │ ├── man-working.png
│ │ ├── shopping.png
│ │ ├── woman-shopping.png
│ │ ├── woman-working.png
│ │ ├── woman-yellow.png
│ │ └── yellow-gradient.png
│ ├── groundhogg-banner.png
│ └── template-library-coming-soon.png
└── js
│ ├── baremetrics-calendar.js
│ ├── baremetrics-calendar.min.js
│ ├── chart.min.js
│ ├── elements.js
│ ├── elements.min.js
│ ├── lib
│ ├── morphdom.js
│ └── morphdom.min.js
│ ├── make-el.js
│ ├── make-el.min.js
│ ├── popup-builder.js
│ ├── popup-builder.min.js
│ ├── popups.js
│ ├── popups.min.js
│ ├── reports.js
│ ├── reports.min.js
│ ├── settings.js
│ └── settings.min.js
├── holler-box.php
├── includes
├── Holler_EDD_SL_Plugin_Updater.php
├── class-holler-admin.php
├── class-holler-api.php
├── class-holler-frontend.php
├── class-holler-integrations.php
├── class-holler-lead.php
├── class-holler-licensing.php
├── class-holler-popup.php
├── class-holler-reporting.php
├── class-holler-settings.php
├── class-holler-telemetry.php
└── class-holler-updater.php
├── languages
├── holler-box.mo
└── holler-box.po
├── readme.txt
└── uninstall.php
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to WordPress.org
2 | on:
3 | push:
4 | tags-ignore:
5 | - "*.dev"
6 | - "*.dev.*"
7 | - "*.beta"
8 | - "*.beta.*"
9 | - "*.alpha"
10 | - "*.alpha.*"
11 | - "*.rc.*"
12 | jobs:
13 | tag:
14 | name: New tag
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@master
18 | - name: Install Subversion
19 | run: sudo apt-get install subversion
20 | - name: WordPress Plugin Deploy
21 | with:
22 | generate-zip: true
23 | uses: 10up/action-wordpress-plugin-deploy@stable
24 | env:
25 | SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
26 | SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
27 | SLUG: holler-box
28 | - name: Create GitHub release
29 | uses: softprops/action-gh-release@v1
30 | with:
31 | files: ${{github.workspace}}/${{ github.event.repository.name }}.zip
32 | env:
33 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34 |
--------------------------------------------------------------------------------
/assets/css/admin.css:
--------------------------------------------------------------------------------
1 | .holler-spinner {
2 | display: block;
3 | height: 15px;
4 | width: 15px;
5 | border: 5px solid rgba(255, 255, 255, 0.4);
6 | border-bottom-color: #ffffff;
7 | border-radius: 50%;
8 | position: relative;
9 | animation: holler-rotation 1s linear infinite;
10 | }
11 |
12 | .widefat th.column-impressions, .widefat th.column-conversions, .widefat th.column-cvr, .widefat td.column-impressions, .widefat td.column-conversions, .widefat td.column-cvr {
13 | text-align: center;
14 | width: 100px;
15 | }
16 |
17 | .holler-header {
18 | padding-left: 30px;
19 | padding-right: 30px;
20 | }
21 | .holler-header #logo svg {
22 | width: 200px;
23 | }
24 |
25 | body.hollerbox_page_hollerbox_reports #wpcontent,
26 | body.hollerbox_page_hollerbox #wpcontent {
27 | padding: 0;
28 | }
29 |
30 | body.hollerbox_page_hollerbox .holler-header {
31 | padding-left: calc( (100% - 800px) / 2 );
32 | padding-right: calc( (100% - 800px) / 2 );
33 | }
34 | body.hollerbox_page_hollerbox #page {
35 | max-width: 800px;
36 | margin: 30px auto;
37 | gap: 30px;
38 | }
39 | body.hollerbox_page_hollerbox #page #settings {
40 | display: flex;
41 | flex-direction: column;
42 | gap: 30px;
43 | width: 100%;
44 | }
45 | body.hollerbox_page_hollerbox #page #settings .disable-credit.disable-changes {
46 | pointer-events: none;
47 | opacity: 0.5;
48 | }
49 | body.hollerbox_page_hollerbox #page #settings .credit {
50 | background: rgba(16, 38, 64, 0.05);
51 | padding: 5px;
52 | border-radius: 5px;
53 | }
54 | body.hollerbox_page_hollerbox #page #settings .danger-zone {
55 | overflow: hidden;
56 | }
57 | body.hollerbox_page_hollerbox #page #settings .danger-zone .holler-panel-header {
58 | background: rgba(233, 31, 79, 0.1);
59 | }
60 | body.hollerbox_page_hollerbox #page #settings .danger-zone .holler-panel-header h2 {
61 | color: #940e2e;
62 | }
63 | body.hollerbox_page_hollerbox #page #right {
64 | width: 260px;
65 | flex-shrink: 0;
66 | display: flex;
67 | flex-direction: column;
68 | gap: 30px;
69 | }
70 | body.hollerbox_page_hollerbox #page #right .holler-menu a {
71 | padding: 16px;
72 | font-size: 14px;
73 | display: flex;
74 | gap: 10px;
75 | }
76 | body.hollerbox_page_hollerbox #page #right .holler-menu a:hover {
77 | background: rgba(16, 38, 64, 0.05);
78 | text-decoration: none;
79 | }
80 | body.hollerbox_page_hollerbox #page #right .holler-menu a svg {
81 | width: 20px;
82 | }
83 | body.hollerbox_page_hollerbox .setup-page {
84 | max-width: 600px;
85 | margin: auto;
86 | }
87 | body.hollerbox_page_hollerbox .setup-page .page-inner > .holler-panel > .inside {
88 | padding: 30px;
89 | padding-bottom: 50px;
90 | }
91 | body.hollerbox_page_hollerbox .setup-page .page-inner > .holler-panel input[type=text],
92 | body.hollerbox_page_hollerbox .setup-page .page-inner > .holler-panel input[type=email] {
93 | width: 100%;
94 | font-size: 16px;
95 | padding: 4px 12px;
96 | }
97 | body.hollerbox_page_hollerbox .setup-page .page-inner .plugin .plugin-actions {
98 | border-top: 1px solid rgba(16, 38, 64, 0.1);
99 | background: rgba(16, 38, 64, 0.02);
100 | }
101 | body.hollerbox_page_hollerbox .setup-page .page-inner .plugin h2 {
102 | margin: 0;
103 | font-size: 22px;
104 | }
105 | body.hollerbox_page_hollerbox .setup-page .page-inner .plugin .icon {
106 | min-width: 80px;
107 | }
108 | body.hollerbox_page_hollerbox .setup-page label,
109 | body.hollerbox_page_hollerbox .setup-page li,
110 | body.hollerbox_page_hollerbox .setup-page p {
111 | font-size: 16px;
112 | }
113 | body.hollerbox_page_hollerbox .setup-page ul {
114 | list-style: disc;
115 | padding-left: 20px;
116 | }
117 | body.hollerbox_page_hollerbox .setup-page #logo {
118 | display: flex;
119 | justify-content: center;
120 | }
121 | body.hollerbox_page_hollerbox .setup-page #logo svg {
122 | width: 300px;
123 | margin: 60px auto;
124 | }
125 |
126 | body.hollerbox_page_hollerbox_reports .popup-links {
127 | font-size: 16px;
128 | }
129 | body.hollerbox_page_hollerbox_reports #holler-app #reports-here {
130 | padding: 30px;
131 | display: grid;
132 | grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
133 | gap: 30px;
134 | }
135 | body.hollerbox_page_hollerbox_reports #holler-app .span-full {
136 | grid-column: span 6;
137 | }
138 | body.hollerbox_page_hollerbox_reports #holler-app .span-half {
139 | grid-column: span 3;
140 | }
141 | body.hollerbox_page_hollerbox_reports #holler-app .span-third {
142 | grid-column: span 2;
143 | }
144 | body.hollerbox_page_hollerbox_reports #holler-app canvas {
145 | height: 500px;
146 | }
147 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel .holler-panel-header h2 {
148 | font-size: 18px;
149 | padding: 16px;
150 | }
151 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel .holler-panel-header h2 .dashicons {
152 | font-size: 20px;
153 | height: 20px;
154 | width: 20px;
155 | }
156 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel .holler-big-number {
157 | font-size: 42px;
158 | font-weight: 500;
159 | margin: 10px 0;
160 | }
161 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel table {
162 | width: 100%;
163 | border-collapse: collapse;
164 | }
165 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel table thead th {
166 | font-weight: 500;
167 | text-align: left;
168 | }
169 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel table th, body.hollerbox_page_hollerbox_reports #holler-app .holler-panel table td {
170 | padding: 12px 16px;
171 | font-size: 16px;
172 | }
173 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel table th:not(:first-child), body.hollerbox_page_hollerbox_reports #holler-app .holler-panel table td:not(:first-child) {
174 | text-align: center;
175 | }
176 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel table th:first-child, body.hollerbox_page_hollerbox_reports #holler-app .holler-panel table td:first-child {
177 | width: 500px;
178 | }
179 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel table tbody tr:nth-child(odd) {
180 | background-color: rgba(0, 117, 255, 0.02);
181 | }
182 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel .pagination {
183 | padding: 12px 16px;
184 | justify-content: flex-end;
185 | }
186 | body.hollerbox_page_hollerbox_reports #holler-app .holler-panel .pagination .ellipsis {
187 | font-size: 20px;
188 | }
189 |
190 | /*# sourceMappingURL=admin.css.map */
191 |
--------------------------------------------------------------------------------
/assets/css/admin.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["admin.scss"],"names":[],"mappings":"AA6BA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAKE;EAGE;EACA;;;AAKN;EACE;EACA;;AAEA;EACE;;;AAMF;AAAA;EACE;;;AAMF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAGE;EACE;EACA;;AAIJ;EACE,YAjFS;EAkFT;EACA;;AAGF;EACE;;AAEA;EACE,YAtFK;;AAuFL;EACE;;AAOR;EACE;EACA;EACA;EACA;EACA;;AAGE;EACE;EACA;EACA;EACA;;AAEA;EACE,YAlHK;EAmHL;;AAGF;EACE;;AAQV;EACE;EACA;;AAII;EACE;EACA;;AAGF;AAAA;EAGE;EACA;EACA;;AAMF;EACE;EACA,YAtJO;;AAyJT;EACE;EACA;;AAGF;EACE;;AAKN;AAAA;AAAA;EAGE;;AAGF;EACE;EACA;;AAGF;EAEE;EACA;;AAEA;EACE;EACA;;;AAQN;EACE;;AAKA;EACE;EAEA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAWE;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAKN;EACE;EACA;EACA;;AAGF;EACE;EACA;;AAGE;EACE;EACA;;AAIJ;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAIJ;EACE,kBAtRO;;AA0RX;EACE;EACA;;AAEA;EACE","file":"admin.css"}
--------------------------------------------------------------------------------
/assets/css/admin.scss:
--------------------------------------------------------------------------------
1 | $primary-blue: rgb(0, 117, 255);
2 | $primary-blue-60: rgba(0, 117, 255, 0.60);
3 | $primary-blue-50: rgba(0, 117, 255, 0.50);
4 | $primary-blue-20: rgba(0, 117, 255, 0.20);
5 | $primary-blue-10: rgba(0, 117, 255, 0.10);
6 | $primary-blue-7: rgba(0, 117, 255, 0.07);
7 | $primary-blue-2: rgba(0, 117, 255, 0.02);
8 | $primary-dark: rgb(16, 38, 64);
9 | $primary-dark-50: rgba(16, 38, 64, 0.5);
10 | $primary-dark-30: rgba(16, 38, 64, 0.3);
11 | $primary-dark-15: rgba(16, 38, 64, 0.15);
12 | $primary-dark-10: rgba(16, 38, 64, 0.10);
13 | $primary-dark-5: rgba(16, 38, 64, 0.05);
14 | $primary-dark-1: rgba(16, 38, 64, 0.02);
15 | $error-red: rgb(233, 31, 79);
16 | $error-red-50: rgba(233, 31, 79, 0.5);
17 | $error-red-10: rgba(233, 31, 79, 0.10);
18 | $secondary-purple: rgb(108, 25, 173);
19 | $alert-yellow-50: rgba(255, 238, 88, 0.50);
20 | $alert-yellow: rgb(255, 238, 88);
21 | $holler-yellow: rgb(232, 173, 11);
22 | $benchmark-orange: rgb(245, 129, 21);
23 | $benchmark-orange-50: rgba(245, 129, 21, 0.50);
24 | $benchmark-orange-25: rgba(245, 129, 21, 0.25);
25 | $action-green: rgb(158, 206, 56);
26 | $action-green-50: rgba(158, 206, 56, 0.5);
27 | $box-shadow: 5px 5px 30px 0 rgba(24, 45, 70, 0.05);
28 | $background-color: #F6F9FB;
29 |
30 | .holler-spinner {
31 | display: block;
32 | height: 15px;
33 | width: 15px;
34 | border: 5px solid rgba(255, 255, 255, 0.4);
35 | border-bottom-color: #ffffff;
36 | border-radius: 50%;
37 | position: relative;
38 | animation: holler-rotation 1s linear infinite;
39 | }
40 |
41 | .widefat {
42 | th, td {
43 | &.column-impressions,
44 | &.column-conversions,
45 | &.column-cvr {
46 | text-align: center;
47 | width: 100px;
48 | }
49 | }
50 | }
51 |
52 | .holler-header {
53 | padding-left: 30px;
54 | padding-right: 30px;
55 |
56 | #logo svg {
57 | width: 200px;
58 | }
59 | }
60 |
61 | body.hollerbox_page_hollerbox_reports,
62 | body.hollerbox_page_hollerbox {
63 | #wpcontent {
64 | padding: 0;
65 | }
66 | }
67 |
68 | body.hollerbox_page_hollerbox {
69 |
70 | .holler-header {
71 | padding-left: calc( (100% - 800px) / 2 );
72 | padding-right: calc( (100% - 800px) / 2 );
73 | }
74 |
75 | #page {
76 | max-width: 800px;
77 | margin: 30px auto;
78 | gap: 30px;
79 |
80 | #settings {
81 | display: flex;
82 | flex-direction: column;
83 | gap: 30px;
84 | width: 100%;
85 |
86 | .disable-credit {
87 | &.disable-changes {
88 | pointer-events: none;
89 | opacity: 0.5;
90 | }
91 | }
92 |
93 | .credit {
94 | background: $primary-dark-5;
95 | padding: 5px;
96 | border-radius: 5px;
97 | }
98 |
99 | .danger-zone {
100 | overflow: hidden;
101 |
102 | .holler-panel-header{
103 | background: $error-red-10;
104 | h2 {
105 | color: darken( $error-red, 20 );
106 | }
107 | }
108 |
109 | }
110 | }
111 |
112 | #right {
113 | width: 260px;
114 | flex-shrink: 0;
115 | display: flex;
116 | flex-direction: column;
117 | gap: 30px;
118 |
119 | .holler-menu {
120 | a {
121 | padding: 16px;
122 | font-size: 14px;
123 | display: flex;
124 | gap: 10px;
125 |
126 | &:hover{
127 | background: $primary-dark-5;
128 | text-decoration: none;
129 | }
130 |
131 | svg {
132 | width: 20px;
133 | }
134 | }
135 | }
136 | }
137 |
138 | }
139 |
140 | .setup-page {
141 | max-width: 600px;
142 | margin: auto;
143 |
144 | .page-inner {
145 | > .holler-panel {
146 | > .inside {
147 | padding: 30px;
148 | padding-bottom: 50px;
149 | }
150 |
151 | input[type="text"],
152 | input[type="email"]
153 | {
154 | width: 100%;
155 | font-size: 16px;
156 | padding: 4px 12px;
157 | }
158 | }
159 |
160 | .plugin {
161 |
162 | .plugin-actions {
163 | border-top: 1px solid $primary-dark-10;
164 | background: $primary-dark-1;
165 | }
166 |
167 | h2 {
168 | margin: 0;
169 | font-size: 22px;
170 | }
171 |
172 | .icon {
173 | min-width: 80px;
174 | }
175 | }
176 | }
177 |
178 | label,
179 | li,
180 | p {
181 | font-size: 16px;
182 | }
183 |
184 | ul {
185 | list-style: disc;
186 | padding-left: 20px;
187 | }
188 |
189 | #logo {
190 |
191 | display: flex;
192 | justify-content: center;
193 |
194 | svg {
195 | width: 300px;
196 | margin: 60px auto;
197 | }
198 | }
199 | }
200 | }
201 |
202 | body.hollerbox_page_hollerbox_reports {
203 |
204 | .popup-links {
205 | font-size: 16px;
206 | }
207 |
208 | #holler-app {
209 |
210 | #reports-here {
211 | padding: 30px;
212 |
213 | display: grid;
214 | grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
215 | gap: 30px;
216 | }
217 |
218 | .span-full {
219 | grid-column: span 6;
220 | }
221 |
222 | .span-half {
223 | grid-column: span 3;
224 | }
225 |
226 | .span-third {
227 | grid-column: span 2;
228 | }
229 |
230 | canvas {
231 | height: 500px;
232 | }
233 |
234 | .holler-panel {
235 |
236 | &.pie .inside{
237 | //padding-top: 0;
238 | //padding-bottom: 0;
239 | }
240 |
241 | .holler-panel-header {
242 | h2 {
243 | font-size: 18px;
244 | padding: 16px;
245 |
246 | .dashicons {
247 | font-size: 20px;
248 | height: 20px;
249 | width: 20px;
250 | }
251 | }
252 | }
253 |
254 | .holler-big-number {
255 | font-size: 42px;
256 | font-weight: 500;
257 | margin: 10px 0;
258 | }
259 |
260 | table {
261 | width: 100%;
262 | border-collapse: collapse;
263 |
264 | thead {
265 | th {
266 | font-weight: 500;
267 | text-align: left;
268 | }
269 | }
270 |
271 | th, td {
272 | padding: 12px 16px;
273 | font-size: 16px;
274 |
275 | &:not(:first-child) {
276 | text-align: center;
277 | }
278 |
279 | &:first-child {
280 | width: 500px;
281 | }
282 | }
283 |
284 | tbody tr:nth-child(odd) {
285 | background-color: $primary-blue-2;
286 | }
287 | }
288 |
289 | .pagination {
290 | padding: 12px 16px;
291 | justify-content: flex-end;
292 |
293 | .ellipsis {
294 | font-size: 20px;
295 | }
296 | }
297 | }
298 |
299 | }
300 |
301 |
302 | }
303 |
--------------------------------------------------------------------------------
/assets/css/calendar.css:
--------------------------------------------------------------------------------
1 | .daterange{position:relative}.daterange *{box-sizing:border-box}.daterange div,.daterange li,.daterange span,.daterange ul{margin:0;padding:0;border:0}.daterange ul{list-style:none}.daterange.dr-active{z-index:10}.daterange .dr-input{display:-webkit-box;display:-ms-flexbox;display:flex;border:1px solid #C3CACD;border-radius:5px;background-color:#FFF;position:relative;z-index:5;overflow:hidden;height:40px}.daterange .dr-input:hover{border-color:#2693D5}.daterange .dr-input.dr-active{box-shadow:0 0 0 3px rgba(38,147,213,.4);border-color:#2693D5}.daterange .dr-input .dr-dates{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;padding:0 1.5rem 0 .75rem;min-width:calc(100% - 35px)}.daterange .dr-input .dr-dates .dr-date{font-size:.9375rem;padding:.65625rem 0;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;outline:0}.daterange .dr-input .dr-dates .dr-date.dr-active,.daterange .dr-input .dr-dates .dr-date:focus,.daterange .dr-input .dr-dates .dr-date:hover{color:#2693D5}.daterange .dr-input .dr-dates .dr-date:empty:after{content:attr(placeholder);color:#9BA3A7}.daterange .dr-input .dr-dates .dr-dates-dash{color:#9BA3A7;padding:0 10px;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;font-weight:600}.daterange .dr-input .dr-presets{width:2.1875rem;border-left:1px solid #C3CACD;-ms-flex-negative:0;flex-shrink:0;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.daterange .dr-input .dr-presets.dr-active,.daterange .dr-input .dr-presets:hover{border-color:#2693D5;box-shadow:inset 0 2px 3px #EBF1F4}.daterange .dr-input .dr-presets.dr-active .dr-preset-bar,.daterange .dr-input .dr-presets:hover .dr-preset-bar{background-color:#2693D5}.daterange .dr-input .dr-presets .dr-preset-bar{height:2px;background-color:#C3CACD;margin:1px 0 1px 25%}.daterange .dr-input .dr-presets .dr-preset-bar:nth-child(1){width:50%}.daterange .dr-input .dr-presets .dr-preset-bar:nth-child(2){width:40%}.daterange .dr-input .dr-presets .dr-preset-bar:nth-child(3){width:30%}.daterange .dr-selections{position:absolute}.daterange .dr-selections .dr-calendar{background-color:#FFF;font-size:.9375rem;box-shadow:0 0 5px #C3CACD;border-radius:5px;position:relative;overflow:hidden;z-index:4;padding-top:5px;top:-5px;left:4px;-webkit-transition:width .2s;transition:width .2s;min-width:210px}.daterange .dr-selections .dr-calendar .dr-range-switcher{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:.375rem .5rem;font-size:.875rem}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid rgba(195,202,205,.5);border-radius:5px;height:1.5625rem}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i{color:#C3CACD;position:relative;top:-1px;cursor:pointer;font-size:.75rem;height:100%;width:20px}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i:hover:after,.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i:hover:before{background-color:#2693D5}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i.dr-disabled{pointer-events:none;opacity:0}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i:after,.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i:before{content:"";position:absolute;width:7px;height:2px;background-color:#C3CACD;border-radius:1px;left:50%}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i.dr-left:before{top:calc(50% - 2px);-webkit-transform:translate(-50%,-50%) rotate(-45deg);transform:translate(-50%,-50%) rotate(-45deg)}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i.dr-left:after{top:calc(50% + 2px);-webkit-transform:translate(-50%,-50%) rotate(45deg);transform:translate(-50%,-50%) rotate(45deg)}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i.dr-right:before{top:calc(50% - 2px);-webkit-transform:translate(-50%,-50%) rotate(45deg);transform:translate(-50%,-50%) rotate(45deg)}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-switcher i.dr-right:after{top:calc(50% + 2px);-webkit-transform:translate(-50%,-50%) rotate(-45deg);transform:translate(-50%,-50%) rotate(-45deg)}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-month-switcher{width:100%;margin-right:.375rem}.daterange .dr-selections .dr-calendar .dr-range-switcher .dr-year-switcher{min-width:80px}.daterange .dr-selections .dr-calendar .dr-days-of-week-list{display:-webkit-box;display:-ms-flexbox;display:flex;background-color:#EBF1F4;font-size:.625rem;color:#9BA3A7;padding:.3125rem 0;border:1px solid rgba(195,202,205,.5);border-left:none;border-right:none}.daterange .dr-selections .dr-calendar .dr-days-of-week-list .dr-day-of-week{width:calc(100% / 7);text-align:center}.daterange .dr-selections .dr-calendar .dr-day-list{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;font-size:.9375rem}.daterange .dr-selections .dr-calendar .dr-day-list .dr-day{padding:.3125rem;text-align:center;width:calc(100% / 7);cursor:pointer;color:#4f565c}.daterange .dr-selections .dr-calendar .dr-day-list .dr-day.dr-hover:not(.dr-current){background-color:#EBF1F4!important}.daterange .dr-selections .dr-calendar .dr-day-list .dr-day.dr-hover-before{border-left:2px solid #2693D5!important;border-radius:2px 0 0 2px;padding-left:.1875rem!important}.daterange .dr-selections .dr-calendar .dr-day-list .dr-day.dr-hover-after{border-right:2px solid #2693D5!important;border-radius:0 2px 2px 0;padding-right:.1875rem!important}.daterange .dr-selections .dr-calendar .dr-day-list .dr-end,.daterange .dr-selections .dr-calendar .dr-day-list .dr-selected,.daterange .dr-selections .dr-calendar .dr-day-list .dr-start{background-color:#EBF1F4}.daterange .dr-selections .dr-calendar .dr-day-list .dr-maybe{background-color:#EBF1F4!important}.daterange .dr-selections .dr-calendar .dr-day-list .dr-fade{color:#C3CACD}.daterange .dr-selections .dr-calendar .dr-day-list .dr-start{border-left:2px solid #2693D5;border-radius:2px 0 0 2px;padding-left:.1875rem}.daterange .dr-selections .dr-calendar .dr-day-list .dr-end{border-right:2px solid #2693D5;border-radius:0 2px 2px 0;padding-right:.1875rem}.daterange .dr-selections .dr-calendar .dr-day-list .dr-current{color:#2693D5!important;background-color:rgba(38,147,213,.2)!important}.daterange .dr-selections .dr-calendar .dr-day-list .dr-outside{pointer-events:none;cursor:default;color:rgba(195,202,205,.5)}.daterange .dr-selections .dr-preset-list{background-color:#FFF;color:#2693D5;font-size:.9375rem;box-shadow:0 0 5px #C3CACD;border-radius:5px;position:relative;overflow:hidden;z-index:4;padding-top:5px;top:-5px;left:4px;width:100%}.daterange .dr-selections .dr-list-item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;padding:.75rem .625rem;border-bottom:1px solid #EBF1F4;cursor:pointer;white-space:nowrap}.daterange .dr-selections .dr-list-item:hover{background-color:#EBF1F4}.daterange .dr-selections .dr-list-item .dr-item-aside{color:#9BA3A7;font-size:.75rem;margin-left:.75rem;position:relative;top:1px}.daterange--single .dr-input{cursor:text}.daterange--single .dr-input .dr-dates{padding:0;min-width:160px;width:100%}.daterange--single .dr-input .dr-dates .dr-date{width:100%;padding:.65625rem .75rem;text-align:left;color:#4f565c}
--------------------------------------------------------------------------------
/assets/css/elements.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["elements.scss"],"names":[],"mappings":";AA2BA;EACE;;;AAIA;EACE;;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAKJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EAEE;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAKJ;EAEE;;AAIE;EACE;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAKF;EACE;;AAKN;EACE;EACA;EACA;;AAEA;EAME;;AAJA;EACE;;AAKF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;;;AAMR;EAEE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;;AAGF;EACE,kBA/Ma;;AAkNf;EACE;;AAEA;EACE,kBA5NW;;;AAiOjB;EAEE;EACA;;AAEA;EACE;EACA;EAEA;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;EACA;EACA;EAEA;EAUA;EACA;EACA;EACA;EACA;;AAZA;EACE,kBArPW;;AAwPb;EACE;;;AAaJ;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA,OA1SY;EA2SZ;EACA;;AAKA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;EACA;;AAOJ;AAAA;EACE;EACA;EACA;;;AAMJ;EAEE,cA1UQ;;AA4UR;EACE,cA7UM;EA8UN;EACA;;;AAMJ;EACE;;AAIA;EACE;;;AAKN;EACE;EACA;EACA,YAxVW;EAyVX;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAKA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEE;EACA;;AAGF;EACE;;AAGF;EACE,OA1YU;;;AAgZlB;EACE;EACA;EACA;;;AAGF;EACE,YA3Ze;EA4Zf;EACA;EACA;EACA,OA7Za;;AA+Zb;EACE,YAtZc;EAuZd;;AAGF;EACE,YAvZkB;EAwZlB;;AAGF;EACE,YA/ac;;AAkbhB;EACE,YA9Zc;EA+Zd;;AAGF;EACE,YA5aW;EA6aX;;AAGF;EACE;;;AAOF;AAAA;AAAA;EACE,OA1bQ;;AA6bV;AAAA;AAAA;EACE,OAxbe;;AA4bjB;AAAA;AAAA;EACE,OA1bW;;AA6bb;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;EACE;;;AAKF;EACE;EACA;;AAEA;EACE;;;AAKN;EACE;EACA;AACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;;AAIJ;EACE;EACA;;AAEA;EACE;;AAIJ;EACE;;AAGF;EAEE;EACA;EACA;;AAEA;EACE;EASA;EACA;EACA;;AATA;EACE;EACA;EACA;EACA;;AAQJ;AAAA;AAAA;EAGE;EACA;;AAEA;AAAA;AAAA;EACE,YAvhBS;;AA0hBX;AAAA;AAAA;EACE;EACA;;AAGF;AAAA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;;AAMF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAOJ;EAEE;;AAEA;EACE;;AAKN;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;;AAOJ;EACE;;AAME;EACE;EACA;EACA;;;AAMR;EACE;EACA;;;AAGF;EACE;IACE;;EAEF;IACE;;;AAIJ;AAAA;AAAA;AAAA;EAIE;;AAEA;AAAA;AAAA;AAAA;EACE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;AAAA;EACE;EACA;;AAIJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAEE;EACA;EAMA;EACA;EACA;EACA;EACA;EACA;;AATA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;;AAUF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAEE;EACA;EACA;EAEA;EACA;EACA,OA/qBS;EAgrBT;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE,YAnrBS;;AAqrBT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;;AAIJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAEE,YAltBS;;AAotBT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA,OAttBO;;AAytBT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE,kBAztBQ;EA0tBR,OA9tBK;;AAmuBX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;EACA,OAtuBS;EAuuBT;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;EACA,OAruBO;;AAwuBT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA,cAjvBO;EAkvBP,kBA5uBS;;AA8uBT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA,YA3uBQ;EA4uBR,OAhvBK;;AAqvBX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE,YAhvBM;;AAkvBN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE,OAnvBI;EAovBJ;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE,OA3vBE;EA4vBF,kBA1vBK;;AA+vBX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA,OAzwBS;EA0wBT;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE,YA1wBU;;AA6wBZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE,kBA9wBU;;AAkxBd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;EACA;EACA;;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;;AAIA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;;AASN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;;AAIJ;AAAA;AAAA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EAEE;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;;;AAMJ;EACE;;AAEA;EACE;EACA;EAOA;EACA;EACA;EAEA;EACA;EACA;EACA;;AAZA;EACE;EACA;;AAYF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAKN;EACE;EACA;EACA;;AAGE;EACE;;AASJ;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EAEE,YAt7BK;EAu7BL;;;AAOV;EACE;EACA;EACA;AACA;EACA;EACA;EACA;EACA,YA96BW;EA+6BX;EACA;;AAEA;EACE;EACA,kBAt7BW;;AAy7Bb;EACE;EACA,kBAp8BQ;;AAu8BV;EACE;EACA,kBAn8Be;;AAs8BjB;EACE;EACA,kBAp9BW;;;AAw9Bf;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAIA;EACE;EACA;;AAMR;EACE;EACA;EACA;;AAEA;EACE;;AAIJ;EACE;;AAGF;EACE;EACA,YA/gCc;EAghCd;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAIJ;EACE;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;;AAKF;EACE;EACA;EACA;;AAGF;EACE;;AAIJ;EACE;;AAEA;EACE;;AAKN;EACE;EACA;EACA;EACA;;AAGF;EAOE;EAEA;EACA;EACA;;AAKF;EACE;EACA;;;AAIJ;EACE;;;AAMF;EACE;EACA;;;AAGF;AAAA;EAEE;EACA;;AAEA;AAAA;AAAA;AAAA;EAEE;;AAEA;AAAA;AAAA;AAAA;EACE;;AAIJ;AAAA;EAQE;EACA;EACA;;AARA;AAAA;EACE;EACA;EACA;;AAQJ;AAAA;EACE;EACA;;;AAIJ;AAAA;EAEE,OAzqCU;;;AA6qCV;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EAEE;;AAEA;EACE;;AAEA;AAAA;EAEE;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAEA;AAAA;EAEE;EACA;;AAGF;EAEE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAIA;AAAA;EAEE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAKF;EACE;;AAKF;AAAA;EAEE;;AAKN;EACE;;AAGA;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;;AAKN;EAEE;EACA;EACA;EACA;EACA;EACA;EACA,YAhyCW;EAiyCX;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EAEA;;AAEA;EACE,kBAl0CY;EAm0CZ;;;AAKN;EAEE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EACE,OA73CO;;AAg4CT;EACE;EACA,kBAl4CO;EAm4CP,cAn4CO;EAo4CP;;;AAOR;EACE;EACA;EACA;;AAEA;EAEE;EACA;EAUA;EACA;EACA;EACA;;AAXA;EACE,kBA14CW;;AA64Cb;EACE;;AASJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE,YA/5CS;EAg6CT;;AAGF;EACE,YA35CY;EA45CZ;;AAGF;EACE;EACA;EACA;;AAEA;EACE,kBAh7CS;;;AAu7CjB;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;;AAIJ;AAAA;EAEE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;EACA;;;AAMN;EACE;EACA;EACA;EACA;;;AAKA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EAEA,kBAr/CgB;EAs/ChB;EACA;EACA;;AAKA;EACE;EAKA;EACA,kBAxgDW;EAygDX;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAIJ;EACE,cA//CW;;AAigDX;EACE,kBAlgDS;;;AAugDf;EAEE;EACA;;AAGE;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA,kBAtiDW;EAuiDX;EACA,YAvhDS;EAwhDT;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;EACA;EAEA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;;AAIJ;EACE;EACA;EAEA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMR;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;;;AAIJ;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAOR;EAEE;EACA;EACA;;AAEA;EACE;EACA;;AAIA;EACE,OAtrDa;;AA2rDf;EACE,OAzrDS;;AA6rDb;EACE;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;;AAGE;EACE;;AAIJ;EACE;;;AAIJ;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;AACA;AACA;AAEA;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AACA;EACE;IACE;;;EAEF;IACE;;;EAEF;IACE;;;EAEF;IACE;;;EAEF;IACE;;;EAEF;IACE;;;EAEF;IACE;;;EAEF;IACE;;;AAKJ;AACA;EACE;EACA;EACA;;;AAIA;EAEE;EACA;EACA;;AAEA;EACE,cAh4DS;EAi4DT,YA93DY;;AAk4DhB;EACE;;;AAKF;EACE;;;AAIJ;EACE;;AAEA;EACE;EAEA;EACA;EACA;;;AAKJ;EACE;EACA;EACA;;;AAGF;EACE;IACE;;;AAIJ;EACE;IACE;;;AAIJ;EACE;IACE;IACA;;;AAKJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACE;;AAEA;EACE;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEA;EACE;;AAIJ;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAKJ;EACE;;AAGF;EACE;;;AAKJ;EAWE;EACA;EACA;;AAXA;EACE;EACA;;AAEA;EACE;;AAQJ;EACE;EAEA;EACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAIJ;EACE;EACA,YA1iEY;EA2iEZ;EACA;EACA;EACA;;AAEA;EACE,YA7iEO;EA8iEP;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE,OAhkEK;EAikEL;;AAMR;EACE;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE,OAvmEO;EAwmEP,YA1mES;;;AAinEjB;EAEE;EACA;EACA,YAtnEgB;EAunEhB,OApnEa;EAqnEb;;AAGA;EACE;EACA;EACA","file":"elements.css"}
--------------------------------------------------------------------------------
/assets/css/popup-builder.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | input#post-title {
3 | font-size: 16px;
4 | min-width: 500px;
5 | }
6 |
7 | .holler-pro-ad {
8 | padding: 20px;
9 | font-size: 18px;
10 | background: #e8ad0b;
11 | color: #fff;
12 | text-align: center;
13 | margin: 20px 30px 0 30px;
14 | border-radius: 5px;
15 | line-height: 1.3;
16 | }
17 | .holler-pro-ad a {
18 | color: #fff;
19 | }
20 |
21 | #triggers .holler-pro-ad {
22 | margin: 0;
23 | }
24 |
25 | .integration-group .holler-pro-ad {
26 | margin: 0;
27 | grid-column: span 3;
28 | }
29 |
30 | .promote-groundhogg img {
31 | max-width: 100%;
32 | border-radius: 5px;
33 | }
34 | .promote-groundhogg h1 {
35 | font-size: 42px;
36 | margin-bottom: 40px;
37 | font-weight: 300;
38 | line-height: 1.1;
39 | }
40 | .promote-groundhogg p, .promote-groundhogg ul, .promote-groundhogg li {
41 | font-size: 18px;
42 | }
43 |
44 | .pro-feature {
45 | max-width: 400px;
46 | }
47 | .pro-feature h1 {
48 | font-size: 42px;
49 | margin-bottom: 40px;
50 | font-weight: 300;
51 | }
52 | .pro-feature p, .pro-feature ul, .pro-feature li {
53 | font-size: 18px;
54 | }
55 |
56 | #wpcontent {
57 | padding: 0;
58 | }
59 |
60 | #wpfooter {
61 | display: none;
62 | }
63 |
64 | @keyframes holler-grow {
65 | from {
66 | max-height: 0;
67 | }
68 | to {
69 | max-height: 100vh;
70 | }
71 | }
72 | table.display-conditions-grid {
73 | box-sizing: border-box;
74 | border-collapse: collapse;
75 | width: 100%;
76 | }
77 | table.display-conditions-grid .picker-here {
78 | margin-top: 10px;
79 | }
80 | table.display-conditions-grid .rules {
81 | display: flex;
82 | flex-direction: column;
83 | gap: 10px;
84 | margin-bottom: 10px;
85 | }
86 | table.display-conditions-grid .rules .rule {
87 | padding-bottom: 10px;
88 | border-bottom: 1px solid rgba(16, 38, 64, 0.15);
89 | }
90 | table.display-conditions-grid .rules select {
91 | max-width: 100%;
92 | }
93 | table.display-conditions-grid th {
94 | text-align: left;
95 | font-size: 16px;
96 | padding: 30px;
97 | border-right: 1px solid rgba(16, 38, 64, 0.15);
98 | }
99 | table.display-conditions-grid td {
100 | width: 100%;
101 | box-sizing: border-box;
102 | padding: 30px;
103 | }
104 | table.display-conditions-grid tr:not(:last-child) td, table.display-conditions-grid tr:not(:last-child) th {
105 | border-bottom: 1px solid rgba(16, 38, 64, 0.15);
106 | }
107 |
108 | #triggers {
109 | display: flex;
110 | flex-direction: column;
111 | gap: 10px;
112 | }
113 | #triggers .trigger {
114 | display: flex;
115 | align-items: center;
116 | justify-content: space-between;
117 | border: 1px solid rgba(16, 38, 64, 0.15);
118 | border-radius: 5px;
119 | padding: 10px 10px 10px 15px;
120 | min-height: 30px;
121 | }
122 | #triggers .trigger input[type=number] {
123 | width: 60px;
124 | }
125 | #triggers .trigger .controls {
126 | display: none;
127 | }
128 | #triggers .trigger.enabled .controls {
129 | display: block;
130 | }
131 | #triggers .trigger.enabled .name {
132 | opacity: 1;
133 | }
134 | #triggers .trigger:hover {
135 | box-shadow: 5px 5px 30px 0 rgba(24, 45, 70, 0.05);
136 | }
137 | #triggers .trigger .name {
138 | font-size: 16px;
139 | font-weight: 500;
140 | opacity: 0.6;
141 | }
142 | #triggers .trigger button {
143 | justify-self: flex-end;
144 | margin-left: auto;
145 | }
146 |
147 | #integrations-here {
148 | padding: 30px;
149 | }
150 | #integrations-here h2 {
151 | font-size: 24px;
152 | }
153 | #integrations-here .integration-group {
154 | margin: 20px 0 40px 0;
155 | box-sizing: content-box;
156 | width: 100%;
157 | display: grid;
158 | grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
159 | gap: 20px;
160 | }
161 | #integrations-here .integration-group:last-child {
162 | margin-bottom: 0;
163 | }
164 | #integrations-here .integration {
165 | position: relative;
166 | min-width: calc(100% / 6);
167 | cursor: pointer;
168 | border-radius: 5px;
169 | background: #ffffff;
170 | border: 1px solid rgba(16, 38, 64, 0.15);
171 | }
172 | #integrations-here .integration:hover {
173 | box-shadow: 5px 5px 30px 0 rgba(24, 45, 70, 0.05);
174 | }
175 | #integrations-here .integration:hover .integration-name {
176 | font-weight: bold;
177 | color: #0075ff;
178 | }
179 | #integrations-here .integration:hover svg {
180 | transform: scale(1.1);
181 | }
182 | #integrations-here .integration .integration-name {
183 | text-align: center;
184 | }
185 | #integrations-here .integration .icon {
186 | border-bottom: 1px solid rgba(16, 38, 64, 0.15);
187 | display: flex;
188 | align-items: center;
189 | justify-content: center;
190 | padding: 0 20px;
191 | height: 110px;
192 | }
193 | #integrations-here .integration .icon svg {
194 | transition: 0.4s;
195 | width: 60px;
196 | height: 60px;
197 | }
198 |
199 | .edit-integration #edit-here {
200 | padding: 30px;
201 | }
202 |
203 | @keyframes lds-facebook {
204 | 0% {
205 | top: 8px;
206 | height: 64px;
207 | }
208 | 50%, 100% {
209 | top: 24px;
210 | height: 32px;
211 | }
212 | }
213 | .lds-facebook {
214 | display: block;
215 | margin: auto;
216 | position: relative;
217 | width: 80px;
218 | height: 80px;
219 | }
220 | .lds-facebook div {
221 | display: inline-block;
222 | position: absolute;
223 | left: 8px;
224 | width: 16px;
225 | background: rgba(16, 38, 64, 0.5);
226 | animation: lds-facebook 1.2s cubic-bezier(0, 0.5, 0.5, 1) infinite;
227 | }
228 | .lds-facebook div:nth-child(1) {
229 | left: 8px;
230 | animation-delay: -0.24s;
231 | }
232 | .lds-facebook div:nth-child(2) {
233 | left: 32px;
234 | animation-delay: -0.12s;
235 | }
236 | .lds-facebook div:nth-child(3) {
237 | left: 56px;
238 | animation-delay: 0s;
239 | }
240 |
241 | #templates .template-filters {
242 | padding-top: 30px;
243 | padding-left: 30px;
244 | }
245 | #templates .template-grid {
246 | box-sizing: border-box;
247 | width: 100%;
248 | display: grid;
249 | grid-template-columns: 1fr 1fr 1fr;
250 | gap: 30px 30px;
251 | grid-auto-flow: row;
252 | padding: 30px;
253 | }
254 | #templates .template-grid.library {
255 | grid-template-columns: 1fr 1fr;
256 | }
257 | #templates .template-grid.library .template .preview-wrap {
258 | height: 300px;
259 | }
260 | #templates .template-grid .template {
261 | box-sizing: content-box;
262 | cursor: pointer;
263 | border-radius: 5px;
264 | border: 1px solid rgba(16, 38, 64, 0.15);
265 | overflow: hidden;
266 | position: relative;
267 | }
268 | #templates .template-grid .template span.pro-template {
269 | position: absolute;
270 | top: 10px;
271 | right: 10px;
272 | background: #e8ad0b;
273 | padding: 4px 6px;
274 | border-radius: 5px;
275 | color: #ffffff;
276 | z-index: 9999;
277 | }
278 | #templates .template-grid .template span.pro-template svg {
279 | height: 14px;
280 | width: 14px;
281 | }
282 | #templates .template-grid .template .template-name {
283 | text-align: center;
284 | }
285 | #templates .template-grid .template .preview-wrap {
286 | overflow: hidden;
287 | height: 250px;
288 | background: rgba(0, 117, 255, 0.02);
289 | border-bottom: 1px solid rgba(16, 38, 64, 0.15);
290 | }
291 | #templates .template-grid .template .preview-wrap .preview {
292 | box-sizing: content-box;
293 | width: 100%;
294 | height: 100%;
295 | position: relative;
296 | zoom: 40%;
297 | }
298 | #templates .template-grid .template .preview-wrap .preview .holler-box .holler-box-overlay,
299 | #templates .template-grid .template .preview-wrap .preview .holler-box .holler-box-overlay::after,
300 | #templates .template-grid .template .preview-wrap .preview .holler-box .holler-box-overlay::before {
301 | position: absolute;
302 | }
303 | #templates .template-grid .template .preview-wrap .preview .holler-box .positioner {
304 | position: absolute;
305 | }
306 | #templates .template-grid .template .preview-wrap .preview .holler-box .holler-box-modal {
307 | transition: 0.3s;
308 | }
309 | #templates .template-grid .template .preview-wrap .preview:not(.show-overlay) .holler-box .holler-box-overlay,
310 | #templates .template-grid .template .preview-wrap .preview:not(.show-overlay) .holler-box .holler-box-overlay::after,
311 | #templates .template-grid .template .preview-wrap .preview:not(.show-overlay) .holler-box .holler-box-overlay::before {
312 | display: none;
313 | }
314 | #templates .template-grid .template:hover {
315 | box-shadow: 5px 5px 30px 0 rgba(24, 45, 70, 0.05);
316 | transition: 0.4s;
317 | }
318 | #templates .template-grid .template:hover .template-name {
319 | font-weight: bold;
320 | color: #0075ff;
321 | }
322 | #templates .template-grid .template:hover .preview-wrap .preview .holler-box-modal {
323 | transform: scale(1.1);
324 | }
325 |
326 | .holler-header:has(.tab-select) {
327 | padding: 0;
328 | min-height: 0;
329 | }
330 | .holler-header:has(.tab-select) .holler-button {
331 | margin-right: 10px;
332 | }
333 |
334 | menu.tab-select {
335 | display: flex;
336 | padding: 0;
337 | margin: 0;
338 | }
339 | menu.tab-select li.tab {
340 | list-style: none;
341 | padding: 20px;
342 | box-sizing: content-box;
343 | font-size: 20px;
344 | font-weight: 500;
345 | cursor: pointer;
346 | margin: 0;
347 | }
348 | menu.tab-select li.tab.active {
349 | color: #0075ff;
350 | border-bottom: #0075ff 3px solid;
351 | }
352 | menu.tab-select li.tab:hover {
353 | background-color: rgba(16, 38, 64, 0.05);
354 | }
355 |
356 | #import-popup {
357 | padding: 100px;
358 | display: flex;
359 | flex-direction: column;
360 | align-items: center;
361 | gap: 10px;
362 | }
363 |
364 | #holler-app {
365 | position: fixed;
366 | top: 32px;
367 | right: 0;
368 | bottom: 0;
369 | left: 160px;
370 | display: flex;
371 | flex-direction: column;
372 | }
373 | #holler-app #header {
374 | background: #ffffff;
375 | display: flex;
376 | gap: 20px;
377 | border-bottom: 1px solid rgba(16, 38, 64, 0.1);
378 | align-items: center;
379 | }
380 | #holler-app #header .holler {
381 | padding: 0 10px;
382 | border-right: 1px solid rgba(16, 38, 64, 0.1);
383 | height: 100%;
384 | display: flex;
385 | align-items: center;
386 | }
387 | #holler-app #header .holler svg {
388 | height: 30px;
389 | width: 30px;
390 | }
391 | #holler-app #header .inside-header {
392 | width: 100%;
393 | display: flex;
394 | justify-content: space-between;
395 | padding: 10px;
396 | align-items: center;
397 | }
398 | #holler-app #header .inside-header h1.holler-title {
399 | margin: 0;
400 | font-size: 20px;
401 | font-weight: 400;
402 | }
403 | #holler-app #header .inside-header h1.holler-title:hover b {
404 | color: #0075ff;
405 | }
406 | #holler-app #editor {
407 | height: 100%;
408 | overflow: auto;
409 | display: flex;
410 | align-items: stretch;
411 | }
412 | #holler-app #editor #frame {
413 | margin: 20px;
414 | width: 100%;
415 | position: relative;
416 | box-sizing: border-box;
417 | overflow: hidden;
418 | border-radius: 5px;
419 | transition: 0.4s;
420 | }
421 | #holler-app #editor #frame.mobile {
422 | width: 480px;
423 | margin-left: auto;
424 | margin-right: auto;
425 | height: 853px;
426 | max-height: calc( 100vh - 32px - 56px - 40px );
427 | }
428 | #holler-app #editor #frame iframe {
429 | overflow: hidden;
430 | height: 100%;
431 | width: 100%;
432 | }
433 | #holler-app #editor #frame #preview.suppress-animations .animation {
434 | animation: none !important;
435 | }
436 | #holler-app #editor #frame #preview .holler-box .holler-box-overlay,
437 | #holler-app #editor #frame #preview .holler-box .holler-box-overlay::after,
438 | #holler-app #editor #frame #preview .holler-box .holler-box-overlay::before {
439 | position: absolute;
440 | border-radius: 5px;
441 | }
442 | #holler-app #editor #frame #preview .holler-box .positioner {
443 | position: absolute;
444 | }
445 | #holler-app #editor .control-wrap {
446 | flex-shrink: 0;
447 | width: 360px;
448 | background: #ffffff;
449 | border-right: 1px solid rgba(16, 38, 64, 0.1);
450 | overflow: auto;
451 | }
452 | #holler-app #editor .control-wrap #controls {
453 | display: flex;
454 | flex-direction: column;
455 | }
456 | #holler-app #editor .control-wrap #controls .control-button {
457 | border: none;
458 | border-bottom: 1px solid rgba(16, 38, 64, 0.1);
459 | background: #FFFFFF;
460 | display: flex;
461 | justify-content: space-between;
462 | cursor: pointer;
463 | padding: 12px 10px 12px 20px;
464 | font-size: 14px;
465 | font-weight: 500;
466 | }
467 | #holler-app #editor .control-wrap #controls .control-button:hover {
468 | background-color: rgba(16, 38, 64, 0.05);
469 | }
470 | #holler-app #editor .control-wrap #controls .control-group {
471 | border-bottom: 1px solid rgba(16, 38, 64, 0.1);
472 | }
473 | #holler-app #editor .control-wrap #controls .control-group hr {
474 | width: calc( 100% + 40px );
475 | margin: 10px -20px;
476 | }
477 | #holler-app #editor .control-wrap #controls .control-group:has(.CodeMirror) .controls {
478 | padding: 0;
479 | }
480 | #holler-app #editor .control-wrap #controls .control-group:has(.CodeMirror) .controls > .CodeMirror {
481 | border: solid rgba(16, 38, 64, 0.1);
482 | border-width: 1px 0 1px 0;
483 | }
484 | #holler-app #editor .control-wrap #controls .control-group:has(.CodeMirror) .controls p {
485 | padding: 0 20px;
486 | }
487 | #holler-app #editor .control-wrap #controls .control-group .control-group-header {
488 | display: flex;
489 | justify-content: space-between;
490 | cursor: pointer;
491 | }
492 | #holler-app #editor .control-wrap #controls .control-group .control-group-header:hover {
493 | background-color: rgba(16, 38, 64, 0.05);
494 | }
495 | #holler-app #editor .control-wrap #controls .control-group .control-group-header .control-group-name {
496 | padding: 12px 0 12px 20px;
497 | font-size: 14px;
498 | font-weight: 500;
499 | }
500 | #holler-app #editor .control-wrap #controls .control-group .control-group-header > button.toggle-indicator {
501 | background: transparent;
502 | border: none;
503 | }
504 | #holler-app #editor .control-wrap #controls .control-group .control-group-header > button.toggle-indicator:hover {
505 | background: rgba(16, 38, 64, 0.05);
506 | }
507 | #holler-app #editor .control-wrap #controls .control-group .control-group-header > button.toggle-indicator:focus {
508 | box-shadow: 0 0 0 1px #0075ff, 0 0 2px 1px rgba(0, 117, 255, 0.6);
509 | outline: 1px solid transparent;
510 | }
511 | #holler-app #editor .control-wrap #controls .control-group .control-group-header > button.toggle-indicator::before {
512 | display: inline-block;
513 | font: normal 20px/1 dashicons;
514 | speak: never;
515 | -webkit-font-smoothing: antialiased;
516 | -moz-osx-font-smoothing: grayscale;
517 | text-decoration: none;
518 | }
519 | #holler-app #editor .control-wrap #controls .control-group .control-group-header > button.toggle-indicator::before {
520 | content: "";
521 | }
522 | #holler-app #editor .control-wrap #controls .control-group.open .controls {
523 | display: flex;
524 | animation: holler-grow 0.5s linear;
525 | overflow: hidden;
526 | }
527 | #holler-app #editor .control-wrap #controls .control-group.open .control-group-header > button.toggle-indicator::before {
528 | content: "";
529 | }
530 | #holler-app #editor .control-wrap #controls .control-group .controls {
531 | display: none;
532 | padding: 20px;
533 | flex-direction: column;
534 | gap: 10px;
535 | }
536 | #holler-app #editor .control-wrap #controls .control-group .controls label {
537 | font-size: 14px;
538 | }
539 | #holler-app #editor .control-wrap #controls .control-group .controls .control {
540 | display: flex;
541 | justify-content: space-between;
542 | align-items: center;
543 | gap: 10px;
544 | }
545 | #holler-app #editor .control-wrap #controls .control-group .controls .control.hidden {
546 | display: none;
547 | }
548 | #holler-app #editor .control-wrap #controls .control-group .controls .control.stacked {
549 | flex-direction: column;
550 | align-items: stretch;
551 | }
552 | #holler-app #editor .control-wrap #controls .control-group .controls .control input[type=number].input {
553 | max-width: 80px;
554 | padding-right: 0;
555 | }
556 | #holler-app #editor .control-wrap #controls .control-group .controls .control .width-control {
557 | display: flex;
558 | }
559 | #holler-app #editor .control-wrap #controls .control-group .controls .control .width-control input.width-number {
560 | max-width: 60px;
561 | padding-right: 0;
562 | }
563 | #holler-app #editor .control-wrap #controls .control-group .controls #integrations {
564 | display: flex;
565 | flex-direction: column;
566 | gap: 10px;
567 | }
568 | #holler-app #editor .control-wrap #controls .control-group .controls #integrations .integration {
569 | cursor: pointer;
570 | display: flex;
571 | align-items: center;
572 | justify-content: flex-start;
573 | gap: 10px;
574 | border: 1px solid rgba(16, 38, 64, 0.15);
575 | border-radius: 5px;
576 | padding: 5px 5px 5px 15px;
577 | }
578 | #holler-app #editor .control-wrap #controls .control-group .controls #integrations .integration:hover {
579 | box-shadow: 5px 5px 30px 0 rgba(24, 45, 70, 0.05);
580 | }
581 | #holler-app #editor .control-wrap #controls .control-group .controls #integrations .integration > .icon {
582 | display: flex;
583 | align-items: center;
584 | }
585 | #holler-app #editor .control-wrap #controls .control-group .controls #integrations .integration > .icon > svg {
586 | height: 20px;
587 | width: 20px;
588 | }
589 | #holler-app #editor .control-wrap #controls .control-group .controls #integrations .integration .name {
590 | font-size: 16px;
591 | }
592 | #holler-app #editor .control-wrap #controls .control-group .controls #integrations .integration button {
593 | justify-self: flex-end;
594 | margin-left: auto;
595 | }
596 |
597 | /*# sourceMappingURL=popup-builder.css.map */
598 |
--------------------------------------------------------------------------------
/assets/css/popup-builder.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["popup-builder.scss"],"names":[],"mappings":";AA4BA;EACE;EACA;;;AAGF;EACE;EACA;EACA,YAjBc;EAkBd;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAKF;EACE;;;AAKF;EACE;EACA;;;AAMF;EACE;EACA;;AAGF;EACE;EAEA;EACA;EACA;;AAGF;EACE;;;AAIJ;EAEE;;AAEA;EACE;EAEA;EACA;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;IACE;;EAGF;IACE;;;AAQJ;EAEE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAIA;EACE;;;AAKN;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAIA;EACE;;AAGF;EACE;;AAIJ;EACE,YA7KO;;AAgLT;EACE;EACA;EACA;;AAGF;EACE;EACA;;;AAKN;EAEE;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAIJ;EAEE;EACA;EACA;EACA;EACA;EACA;;AAEA;EAME,YAjOO;;AA4NP;EACE;EACA,OAvPO;;AA4PT;EACE;;AAKJ;EACE;;AAGF;EACE;EAEA;EACA;EACA;EACA;EAEA;;AAEA;EACE;EACA;EACA;;;AASN;EACE;;;AAIJ;EACE;IACE;IACA;;EAEF;IACE;IACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA,YAhTc;EAiTd;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAOJ;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA,YA7VQ;EA8VR;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;EACA,YA7XS;EA8XT;;AAEA;EACE;EAEA;EACA;EAEA;EACA;;AAGE;AAAA;AAAA;EAIE;;AAGF;EACE;;AAGF;EACE;;AAMA;AAAA;AAAA;EAIE;;AAOV;EAEE,YAtZK;EAuZL;;AAEA;EACE;EACA,OApbK;;AAwbL;EACE;;;AAQZ;EACE;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE,OAzdS;EA0dT;;AAGF;EACE,kBAldW;;;AAudjB;EACE;EACA;EACA;EACA;EACA;;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGE;EACE,OAvhBG;;AA8hBb;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAME;EACE;;AAKF;AAAA;AAAA;EAIE;EACA;;AAGF;EACE;;AAMR;EACE;EACA;EACA;EACA;EACA;;AAEA;EAEE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE,kBA/lBK;;AAqmBT;EACE;;AAEA;EACE;EACA;;AAIA;EACE;;AAEA;EACE;EACA;;AAGF;EAEE;;AAKN;EACE;EACA;EACA;;AAEA;EACE,kBAnoBG;;AAsoBL;EACE;EACA;EACA;;AAGF;EACE;EACA;;AAEA;EACE,YAjpBC;;AAopBH;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAKF;EACE;;AAMJ;EACE;EACA;EACA;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;;AAEA;EACE;EACA;;AAMN;EAEE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE,YAnuBL;;AAsuBG;EAEE;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;EACA","file":"popup-builder.css"}
--------------------------------------------------------------------------------
/assets/css/popup-builder.scss:
--------------------------------------------------------------------------------
1 | $primary-blue: rgb(0, 117, 255);
2 | $primary-blue-60: rgba(0, 117, 255, 0.60);
3 | $primary-blue-50: rgba(0, 117, 255, 0.50);
4 | $primary-blue-20: rgba(0, 117, 255, 0.20);
5 | $primary-blue-10: rgba(0, 117, 255, 0.10);
6 | $primary-blue-7: rgba(0, 117, 255, 0.07);
7 | $primary-blue-2: rgba(0, 117, 255, 0.02);
8 | $primary-dark: rgb(16, 38, 64);
9 | $primary-dark-50: rgba(16, 38, 64, 0.5);
10 | $primary-dark-30: rgba(16, 38, 64, 0.3);
11 | $primary-dark-15: rgba(16, 38, 64, 0.15);
12 | $primary-dark-10: rgba(16, 38, 64, 0.10);
13 | $primary-dark-5: rgba(16, 38, 64, 0.05);
14 | $error-red: rgb(233, 31, 79);
15 | $error-red-50: rgba(233, 31, 79, 0.5);
16 | $error-red-10: rgba(233, 31, 79, 0.10);
17 | $secondary-purple: rgb(108, 25, 173);
18 | $alert-yellow-50: rgba(255, 238, 88, 0.50);
19 | $alert-yellow: rgb(255, 238, 88);
20 | $holler-yellow: rgb(232, 173, 11);
21 | $benchmark-orange: rgb(245, 129, 21);
22 | $benchmark-orange-50: rgba(245, 129, 21, 0.50);
23 | $benchmark-orange-25: rgba(245, 129, 21, 0.25);
24 | $action-green: rgb(158, 206, 56);
25 | $action-green-50: rgba(158, 206, 56, 0.5);
26 | $box-shadow: 5px 5px 30px 0 rgba(24, 45, 70, 0.05);
27 | $background-color: #F6F9FB;
28 |
29 | input#post-title{
30 | font-size: 16px;
31 | min-width: 500px;
32 | }
33 |
34 | .holler-pro-ad {
35 | padding: 20px;
36 | font-size: 18px;
37 | background: $holler-yellow;
38 | color: #fff;
39 | text-align: center;
40 | margin: 20px 30px 0 30px;
41 | border-radius: 5px;
42 | line-height: 1.3;
43 |
44 | a {
45 | color: #fff;
46 | }
47 | }
48 |
49 | #triggers {
50 | .holler-pro-ad {
51 | margin: 0;
52 | }
53 | }
54 |
55 | .integration-group {
56 | .holler-pro-ad {
57 | margin: 0;
58 | grid-column: span 3;
59 | }
60 | }
61 |
62 | .promote-groundhogg {
63 |
64 | img {
65 | max-width: 100%;
66 | border-radius: 5px;
67 | }
68 |
69 | h1 {
70 | font-size: 42px;
71 | //text-align: center;
72 | margin-bottom: 40px;
73 | font-weight: 300;
74 | line-height: 1.1;
75 | }
76 |
77 | p, ul, li {
78 | font-size: 18px;
79 | }
80 | }
81 |
82 | .pro-feature {
83 |
84 | max-width: 400px;
85 |
86 | h1 {
87 | font-size: 42px;
88 | //text-align: center;
89 | margin-bottom: 40px;
90 | font-weight: 300;
91 | }
92 |
93 | p, ul, li {
94 | font-size: 18px;
95 | }
96 | }
97 |
98 | #wpcontent {
99 | padding: 0;
100 | }
101 |
102 | #wpfooter {
103 | display: none;
104 | }
105 |
106 | @keyframes holler-grow {
107 | from {
108 | max-height: 0;
109 | }
110 |
111 | to {
112 | max-height: 100vh;
113 | }
114 | }
115 |
116 | #text-content {
117 |
118 | }
119 |
120 | table.display-conditions-grid {
121 |
122 | box-sizing: border-box;
123 | border-collapse: collapse;
124 | width: 100%;
125 |
126 | .picker-here {
127 | margin-top: 10px;
128 | }
129 |
130 | .rules {
131 | display: flex;
132 | flex-direction: column;
133 | gap: 10px;
134 | margin-bottom: 10px;
135 |
136 | .rule {
137 | padding-bottom: 10px;
138 | border-bottom: 1px solid $primary-dark-15;
139 | }
140 |
141 | select {
142 | max-width: 100%;
143 | }
144 | }
145 |
146 | th {
147 | text-align: left;
148 | font-size: 16px;
149 | padding: 30px;
150 | border-right: 1px solid $primary-dark-15;
151 | }
152 |
153 | td {
154 | width: 100%;
155 | box-sizing: border-box;
156 | padding: 30px;
157 | }
158 |
159 | tr:not(:last-child) {
160 | td, th {
161 | border-bottom: 1px solid $primary-dark-15;
162 | }
163 | }
164 | }
165 |
166 | #triggers {
167 | display: flex;
168 | flex-direction: column;
169 | gap: 10px;
170 |
171 | .trigger {
172 | display: flex;
173 | align-items: center;
174 | justify-content: space-between;
175 | border: 1px solid $primary-dark-15;
176 | border-radius: 5px;
177 | padding: 10px 10px 10px 15px;
178 | min-height: 30px;
179 |
180 | input[type=number] {
181 | width: 60px;
182 | }
183 |
184 | .controls {
185 | display: none;
186 | }
187 |
188 | &.enabled {
189 | .controls {
190 | display: block;
191 | }
192 |
193 | .name {
194 | opacity: 1;
195 | }
196 | }
197 |
198 | &:hover {
199 | box-shadow: $box-shadow;
200 | }
201 |
202 | .name {
203 | font-size: 16px;
204 | font-weight: 500;
205 | opacity: 0.6;
206 | }
207 |
208 | button {
209 | justify-self: flex-end;
210 | margin-left: auto;
211 | }
212 | }
213 | }
214 |
215 | #integrations-here {
216 |
217 | padding: 30px;
218 |
219 | h2 {
220 | font-size: 24px;
221 | }
222 |
223 | .integration-group {
224 | margin: 20px 0 40px 0;
225 | box-sizing: content-box;
226 | width: 100%;
227 | display: grid;
228 | grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
229 | gap: 20px;
230 |
231 | &:last-child {
232 | margin-bottom: 0;
233 | }
234 | }
235 |
236 | .integration {
237 |
238 | position: relative;
239 | min-width: calc(100% / 6);
240 | cursor: pointer;
241 | border-radius: 5px;
242 | background: #ffffff;
243 | border: 1px solid $primary-dark-15;
244 |
245 | &:hover {
246 | .integration-name {
247 | font-weight: bold;
248 | color: $primary-blue;
249 | }
250 |
251 | box-shadow: $box-shadow;
252 |
253 | svg {
254 | transform: scale(1.1);
255 | }
256 |
257 | }
258 |
259 | .integration-name {
260 | text-align: center;
261 | }
262 |
263 | .icon {
264 | border-bottom: 1px solid $primary-dark-15;
265 |
266 | display: flex;
267 | align-items: center;
268 | justify-content: center;
269 | padding: 0 20px;
270 |
271 | height: 110px;
272 |
273 | svg {
274 | transition: 0.4s;
275 | width: 60px;
276 | height: 60px;
277 | }
278 |
279 | }
280 |
281 | }
282 | }
283 |
284 | .edit-integration {
285 | #edit-here {
286 | padding: 30px;
287 | }
288 | }
289 |
290 | @keyframes lds-facebook {
291 | 0% {
292 | top: 8px;
293 | height: 64px;
294 | }
295 | 50%, 100% {
296 | top: 24px;
297 | height: 32px;
298 | }
299 | }
300 |
301 | .lds-facebook {
302 | display: block;
303 | margin: auto;
304 | position: relative;
305 | width: 80px;
306 | height: 80px;
307 |
308 | div {
309 | display: inline-block;
310 | position: absolute;
311 | left: 8px;
312 | width: 16px;
313 | background: $primary-dark-50;
314 | animation: lds-facebook 1.2s cubic-bezier(0, 0.5, 0.5, 1) infinite;
315 |
316 | &:nth-child(1) {
317 | left: 8px;
318 | animation-delay: -0.24s;
319 | }
320 |
321 | &:nth-child(2) {
322 | left: 32px;
323 | animation-delay: -0.12s;
324 | }
325 |
326 | &:nth-child(3) {
327 | left: 56px;
328 | animation-delay: 0s;
329 | }
330 | }
331 | }
332 |
333 | #templates {
334 |
335 | .template-filters{
336 | padding-top: 30px;
337 | padding-left: 30px;
338 | }
339 |
340 | .template-grid {
341 | box-sizing: border-box;
342 | width: 100%;
343 | display: grid;
344 | grid-template-columns: 1fr 1fr 1fr;
345 | gap: 30px 30px;
346 | grid-auto-flow: row;
347 | padding: 30px;
348 |
349 | &.library {
350 | grid-template-columns: 1fr 1fr;
351 |
352 | .template .preview-wrap{
353 | height: 300px;
354 | }
355 | }
356 |
357 | .template {
358 | box-sizing: content-box;
359 | cursor: pointer;
360 | border-radius: 5px;
361 | border: 1px solid $primary-dark-15;
362 | overflow: hidden;
363 | position: relative;
364 |
365 | span.pro-template {
366 | position: absolute;
367 | top: 10px;
368 | right: 10px;
369 | background: $holler-yellow;
370 | padding: 4px 6px;
371 | border-radius: 5px;
372 | color: #ffffff;
373 | z-index: 9999;
374 |
375 | svg {
376 | height: 14px;
377 | width: 14px;
378 | }
379 | }
380 |
381 | .template-name {
382 | text-align: center;
383 | }
384 |
385 | .preview-wrap {
386 | overflow: hidden;
387 | height: 250px;
388 | background: $primary-blue-2;
389 | border-bottom: 1px solid $primary-dark-15;
390 |
391 | .preview {
392 | box-sizing: content-box;
393 |
394 | width: 100%;
395 | height: 100%;
396 |
397 | position: relative;
398 | zoom: 40%;
399 |
400 | .holler-box {
401 | .holler-box-overlay,
402 | .holler-box-overlay::after,
403 | .holler-box-overlay::before,
404 | {
405 | position: absolute;
406 | }
407 |
408 | .positioner {
409 | position: absolute;
410 | }
411 |
412 | .holler-box-modal {
413 | transition: .3s;
414 | }
415 | }
416 |
417 | &:not(.show-overlay) {
418 | .holler-box {
419 | .holler-box-overlay,
420 | .holler-box-overlay::after,
421 | .holler-box-overlay::before,
422 | {
423 | display: none;
424 | }
425 | }
426 | }
427 | }
428 | }
429 |
430 | &:hover {
431 |
432 | box-shadow: $box-shadow;
433 | transition: 0.4s;
434 |
435 | .template-name {
436 | font-weight: bold;
437 | color: $primary-blue;
438 | }
439 |
440 | .preview-wrap {
441 | .preview .holler-box-modal {
442 | transform: scale(1.1);
443 | }
444 | }
445 | }
446 | }
447 | }
448 | }
449 |
450 | .holler-header:has(.tab-select){
451 | padding: 0;
452 | min-height: 0;
453 |
454 | .holler-button {
455 | margin-right: 10px;
456 | }
457 | }
458 |
459 | menu.tab-select{
460 | display: flex;
461 | padding: 0;
462 | margin: 0;
463 |
464 | li.tab {
465 | list-style: none;
466 | padding: 20px;
467 | box-sizing: content-box;
468 | font-size: 20px;
469 | font-weight: 500;
470 | cursor: pointer;
471 | margin: 0;
472 |
473 | &.active {
474 | color: $primary-blue;
475 | border-bottom: $primary-blue 3px solid;
476 | }
477 |
478 | &:hover{
479 | background-color: $primary-dark-5;
480 | }
481 | }
482 | }
483 |
484 | #import-popup{
485 | padding: 100px;
486 | display: flex;
487 | flex-direction: column;
488 | align-items: center;
489 | gap: 10px;
490 | }
491 |
492 | #holler-app {
493 |
494 | position: fixed;
495 | top: 32px;
496 | right: 0;
497 | bottom: 0;
498 | left: 160px;
499 | display: flex;
500 | flex-direction: column;
501 |
502 | #header {
503 | background: #ffffff;
504 | display: flex;
505 | gap: 20px;
506 | border-bottom: 1px solid $primary-dark-10;
507 | align-items: center;
508 |
509 | .holler {
510 | padding: 0 10px;
511 | border-right: 1px solid $primary-dark-10;
512 | height: 100%;
513 | display: flex;
514 | align-items: center;
515 |
516 | svg {
517 | height: 30px;
518 | width: 30px;
519 | }
520 | }
521 |
522 | .inside-header {
523 | width: 100%;
524 | display: flex;
525 | justify-content: space-between;
526 | padding: 10px;
527 | align-items: center;
528 |
529 | h1.holler-title {
530 | margin: 0;
531 | font-size: 20px;
532 | font-weight: 400;
533 |
534 | &:hover {
535 | b {
536 | color: $primary-blue;
537 | }
538 | }
539 | }
540 | }
541 | }
542 |
543 | #editor {
544 | height: 100%;
545 | overflow: auto;
546 | display: flex;
547 | align-items: stretch;
548 |
549 | #frame {
550 | margin: 20px;
551 | width: 100%;
552 | position: relative;
553 | box-sizing: border-box;
554 | overflow: hidden;
555 | border-radius: 5px;
556 | transition: 0.4s;
557 |
558 | &.mobile {
559 | width: 480px;
560 | margin-left: auto;
561 | margin-right: auto;
562 | height: 853px;
563 | max-height: calc( 100vh - 32px - 56px - 40px );
564 | }
565 |
566 | iframe {
567 | overflow: hidden;
568 | height: 100%;
569 | width: 100%;
570 | }
571 |
572 | #preview {
573 |
574 | &.suppress-animations {
575 | .animation {
576 | animation: none !important;
577 | }
578 | }
579 |
580 | .holler-box {
581 | .holler-box-overlay,
582 | .holler-box-overlay::after,
583 | .holler-box-overlay::before
584 | {
585 | position: absolute;
586 | border-radius: 5px;
587 | }
588 |
589 | .positioner {
590 | position: absolute;
591 | }
592 | }
593 | }
594 | }
595 |
596 | .control-wrap {
597 | flex-shrink: 0;
598 | width: 360px;
599 | background: #ffffff;
600 | border-right: 1px solid $primary-dark-10;
601 | overflow: auto;
602 |
603 | #controls {
604 |
605 | display: flex;
606 | flex-direction: column;
607 |
608 | .control-button {
609 | border: none;
610 | border-bottom: 1px solid $primary-dark-10;
611 | background: #FFFFFF;
612 | display: flex;
613 | justify-content: space-between;
614 | cursor: pointer;
615 | padding: 12px 10px 12px 20px;
616 | font-size: 14px;
617 | font-weight: 500;
618 |
619 | &:hover {
620 | background-color: $primary-dark-5;
621 | }
622 |
623 |
624 | }
625 |
626 | .control-group {
627 | border-bottom: 1px solid $primary-dark-10;
628 |
629 | hr {
630 | width: calc( 100% + 40px );
631 | margin: 10px -20px;
632 | }
633 |
634 | &:has(.CodeMirror) {
635 | .controls {
636 | padding: 0;
637 |
638 | > .CodeMirror {
639 | border: solid $primary-dark-10;
640 | border-width: 1px 0 1px 0;
641 | }
642 |
643 | p {
644 | //text-align: center;
645 | padding: 0 20px;
646 | }
647 | }
648 | }
649 |
650 | .control-group-header {
651 | display: flex;
652 | justify-content: space-between;
653 | cursor: pointer;
654 |
655 | &:hover {
656 | background-color: $primary-dark-5;
657 | }
658 |
659 | .control-group-name {
660 | padding: 12px 0 12px 20px;
661 | font-size: 14px;
662 | font-weight: 500;
663 | }
664 |
665 | > button.toggle-indicator {
666 | background: transparent;
667 | border: none;
668 |
669 | &:hover {
670 | background: $primary-dark-5;
671 | }
672 |
673 | &:focus {
674 | box-shadow: 0 0 0 1px $primary-blue, 0 0 2px 1px $primary-blue-60;
675 | outline: 1px solid transparent;
676 | }
677 |
678 | &::before {
679 | display: inline-block;
680 | font: normal 20px/1 dashicons;
681 | speak: never;
682 | -webkit-font-smoothing: antialiased;
683 | -moz-osx-font-smoothing: grayscale;
684 | text-decoration: none;
685 | }
686 | }
687 |
688 | > button {
689 | &.toggle-indicator::before {
690 | content: "\f140";
691 | }
692 | }
693 | }
694 |
695 | &.open {
696 | .controls {
697 | display: flex;
698 | animation: holler-grow 0.5s linear;
699 | overflow: hidden;
700 | }
701 |
702 | .control-group-header > button.toggle-indicator::before {
703 | content: "\f142";
704 | }
705 | }
706 |
707 | .controls {
708 | display: none;
709 | padding: 20px;
710 | flex-direction: column;
711 | gap: 10px;
712 |
713 | label {
714 | font-size: 14px;
715 | }
716 |
717 | .control {
718 | display: flex;
719 | justify-content: space-between;
720 | align-items: center;
721 | gap: 10px;
722 |
723 | &.hidden{
724 | display: none;
725 | }
726 |
727 | &.stacked{
728 | flex-direction: column;
729 | align-items: stretch;
730 | }
731 |
732 | input[type=number].input{
733 | max-width: 80px;
734 | padding-right: 0;
735 | }
736 |
737 | .width-control{
738 | display: flex;
739 |
740 | input.width-number {
741 | max-width: 60px;
742 | padding-right: 0;
743 | }
744 | }
745 | }
746 |
747 |
748 | #integrations {
749 |
750 | display: flex;
751 | flex-direction: column;
752 | gap: 10px;
753 |
754 | .integration {
755 | cursor: pointer;
756 | display: flex;
757 | align-items: center;
758 | justify-content: flex-start;
759 | gap: 10px;
760 | border: 1px solid $primary-dark-15;
761 | border-radius: 5px;
762 | padding: 5px 5px 5px 15px;
763 |
764 | &:hover {
765 | box-shadow: $box-shadow;
766 | }
767 |
768 | > .icon {
769 |
770 | display: flex;
771 | align-items: center;
772 |
773 | > svg {
774 | height: 20px;
775 | width: 20px;
776 | }
777 | }
778 |
779 | .name {
780 | font-size: 16px;
781 | }
782 |
783 | button {
784 | justify-self: flex-end;
785 | margin-left: auto;
786 | }
787 | }
788 | }
789 | }
790 | }
791 | }
792 | }
793 | }
794 | }
795 |
--------------------------------------------------------------------------------
/assets/css/popups.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["popups.scss"],"names":[],"mappings":"AA6BA;EACE;;;AAIA;EACE;;AAIA;AAAA;EAEE;;AAIJ;EACE;EACA;EACA;EACA;;AAGF;EACE;;;AAMF;EACE;;AAMI;EACE;;AAGF;EACE;;AAGF;EACE;;AAKN;AAAA;EAEE;;;AAKN;EACE;IACE;;EAEF;IACE;;;AAIJ;EACE;IACE;;EAEF;IACE;;;AAIJ;EACE;IACE;;;AAIJ;EACE;IACE;IACA;;EAGF;IACE;IACA;;EAGF;IACE;;;AAIJ;EACE;IACE;IACA;;;AAIJ;EACE;IACE;IACA;;EAEF;IACE;;;AAIJ;EACE;IACE;IACA;;EAEF;IACE;;;AAIJ;EACE;IACE;IACA;;EAEF;IACE;;;AAIJ;EACE;IACE;IACA;;EAEF;IACE;;;AAKJ;EACE;IACE;;EAEF;IACE;IACA;;;AAKJ;EACE;IACE;;EAEF;IACE;IACA;;;AAIJ;EACE;IACE;;EAEF;IACE;IACA;;;AAKJ;EACE;IACE;;EAEF;IACE;IACA;;;AAIJ;EACE;;AAEA;EACE;EACA,OAjNQ;EAkNR;EACA;;AAEA;EACE;;AAGF;EACE;;AAKF;AAAA;AAAA;AAAA;EAIE;;AAIJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAIJ;EAEE;;AAEA;EAEE;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAQJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAON;EAEE;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAMR;EAQE;EACA;;AAPA;EACE,OAxYU;EAyYV;EACA;;AAOJ;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EAaA;;AAXA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAKF;EACE;;AAIJ;EACE;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA,YA7bS;;AA+bT;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YAheS;EAieT,YAzcO;EA0cP;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAUJ;EAEE;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OA9hBS;;AAgiBT;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AASN;EAQE;EACA;;AAPA;EACE,OAhkBQ;EAikBR;EACA;;AAOJ;AAME;AAKA;AAMA;;AAfA;EACE;;AAIF;EACE,YAhmBS;;AAomBX;EACE,YAxmBU;EAymBV;;AAIF;EACE,YA/mBU;;AAknBZ;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA,OA/nBQ;EAgoBR;EACA;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA,YArpBK;EAspBL;EACA;EAGA;EACA;EACA;;AAGA;EACE,YAhqBG;EAiqBH;EACA;EACA;EACA;;AAKN;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;;AAEA;EACE;EACA,YAvrBK;EAwrBL;EACA;EACA;EACA;;AAKN;EACE;EACA;EACA;EACA;;AAEA;AAAA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAUA;;AARA;AAAA;EACE;;AAGF;AAAA;EACE;;AAMJ;EAEE;EACA;EACA,YAvuBK;EAwuBL;EACA;EACA;;AAEA;EAEE,YA7uBM;;AAgvBR;EACE;EACA;;AAQN;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAOJ;EACE;;AAEA;EACE;;AAGF;EACE;EACA,YAtwBO;EAuwBP;EACA;EACA;;AAGF;EACE;EACA;;AAMN;EACE;EACA;EACA,YA3wBO;EA4wBP;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA,kBA/yBS;EAgzBT;;AAEA;EACE;EAEA;EACA;;AAEA;EACE;;AAGF;EACE;;AAQR;EACE;;AAKF;EACE;;AAMF;EACE;;AAEA;EACE;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAOJ;EACE;;AAEA;EACE;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAOJ;EACE;;AAEA;EACE;;AAIJ;EACE;EAEA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA,YAv6BW;;AAg7BX;EAEE;EACA;EACA;;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;;AAEA;EACE;EACA;;AAMR;EAME;EACA;EACA;;AANA;EACE;;AAOF;EACE;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAQJ;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA,kBA5gCS;;AAohCb;EACE;EACA;;AAEA;EACE;;AAUN;AAAA;AAAA;AAAA;AAAA;EAME;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;AAAA;AAAA;AAAA;AAAA;EACE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;;AAOJ;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAKA;EACE;EACA;;AAEA;EACE;;AAKN;EACE;EACA;EACA;;AAEA;EACE;;AAKF;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAUA;;AARA;EACE;;AAGF;EACE;;;AAUR;EAGI;IACE;IACA;;;EAOA;IACE;IACA;;EAGF;IAGE;IACA;;EAEA;IACE;;EAIJ;IAME;IACA;IACA;;EAEA;IACE;;EAKJ;IAME;;EAEA;IACE;;EAIJ;IAGE;;EAEA;IACE;IACA;;EAIJ;IACE;;EAEA;IACE;IACA;;;EASN;IAME;IACA;;EALA;IACE;;EAMF;IACE;;EAEA;IACE;IACA;;EAGF;IACE;IACA;;EAMF;IACE;IACA;IACA;;EAGF;IACE;;EAOJ;IACE","file":"popups.css"}
--------------------------------------------------------------------------------
/assets/img/default/cafe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/cafe.png
--------------------------------------------------------------------------------
/assets/img/default/city-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/city-day.png
--------------------------------------------------------------------------------
/assets/img/default/city-night.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/city-night.png
--------------------------------------------------------------------------------
/assets/img/default/clothes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/clothes.png
--------------------------------------------------------------------------------
/assets/img/default/man-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/man-blue.png
--------------------------------------------------------------------------------
/assets/img/default/man-thumbs-up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/man-thumbs-up.png
--------------------------------------------------------------------------------
/assets/img/default/man-working.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/man-working.png
--------------------------------------------------------------------------------
/assets/img/default/shopping.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/shopping.png
--------------------------------------------------------------------------------
/assets/img/default/woman-shopping.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/woman-shopping.png
--------------------------------------------------------------------------------
/assets/img/default/woman-working.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/woman-working.png
--------------------------------------------------------------------------------
/assets/img/default/woman-yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/woman-yellow.png
--------------------------------------------------------------------------------
/assets/img/default/yellow-gradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/default/yellow-gradient.png
--------------------------------------------------------------------------------
/assets/img/groundhogg-banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/groundhogg-banner.png
--------------------------------------------------------------------------------
/assets/img/template-library-coming-soon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/assets/img/template-library-coming-soon.png
--------------------------------------------------------------------------------
/assets/js/baremetrics-calendar.min.js:
--------------------------------------------------------------------------------
1 | "use strict";(function(root,factory){if(typeof define==="function"&&define.amd){define(["jquery","moment"],factory)}else if(typeof exports==="object"){module.exports=factory(require("jquery"),require("moment"))}else{root.Calendar=factory(jQuery,moment)}})(this,function($,moment){function Calendar(settings){var self=this;this.settings=settings;this.calIsOpen=false;this.presetIsOpen=false;this.sameDayRange=settings.same_day_range||false;this.element=settings.element||$(".daterange");this.selected=null;this.type=this.element.hasClass("daterange--single")?"single":"double";this.required=settings.required==false?false:true;this.format=settings.format||{};this.format.input=settings.format&&settings.format.input||"MMMM D, YYYY";this.format.preset=settings.format&&settings.format.preset||"ll";this.format.jump_month=settings.format&&settings.format.jump_month||"MMMM";this.format.jump_year=settings.format&&settings.format.jump_year||"YYYY";this.placeholder=settings.placeholder||this.format.input;this.days_array=settings.days_array&&settings.days_array.length==7?settings.days_array:moment.weekdaysMin();this.orig_start_date=null;this.orig_end_date=null;this.orig_current_date=null;this.earliest_date=settings.earliest_date?moment(settings.earliest_date):moment("1900-01-01","YYYY-MM-DD");this.latest_date=settings.latest_date?moment(settings.latest_date):moment("2900-12-31","YYYY-MM-DD");this.end_date=settings.end_date?moment(settings.end_date):this.type=="double"?moment():null;this.start_date=settings.start_date?moment(settings.start_date):this.type=="double"?this.end_date.clone().subtract(1,"month"):null;this.current_date=settings.current_date?moment(settings.current_date):this.type=="single"?moment():null;this.presets=settings.presets==false||this.type=="single"?false:true;this.callback=settings.callback||this.calendarSetDates;this.calendarHTML(this.type);$(".dr-presets",this.element).click(function(){self.presetToggle()});$(".dr-list-item",this.element).click(function(){var start=$(".dr-item-aside",this).data("start");var end=$(".dr-item-aside",this).data("end");self.start_date=self.calendarCheckDate(start);self.end_date=self.calendarCheckDate(end);self.calendarSetDates();self.presetToggle();self.calendarSaveDates()});$(".dr-date",this.element).on({click:function(){self.calendarOpen(this)},keyup:function(event){if(event.keyCode==9&&!self.calIsOpen&&!self.start_date&&!self.end_date)self.calendarOpen(this)},keydown:function(event){switch(event.keyCode){case 9:if($(self.selected).hasClass("dr-date-start")){event.preventDefault();self.calendarCheckDates();self.calendarSetDates();$(".dr-date-end",self.element).trigger("click")}else{self.calendarCheckDates();self.calendarSetDates();self.calendarSaveDates();self.calendarClose("force")}break;case 13:event.preventDefault();self.calendarCheckDates();self.calendarSetDates();self.calendarSaveDates();self.calendarClose("force");break;case 27:self.calendarSetDates();self.calendarClose("force");break;case 38:event.preventDefault();var timeframe="day";if(event.shiftKey)timeframe="week";if(event.metaKey)timeframe="month";var back=moment(self.current_date).subtract(1,timeframe);$(this).html(back.format(self.format.input));self.current_date=back;break;case 40:event.preventDefault();var timeframe="day";if(event.shiftKey)timeframe="week";if(event.metaKey)timeframe="month";var forward=moment(self.current_date).add(1,timeframe);$(this).html(forward.format(self.format.input));self.current_date=forward;break}}});$(".dr-month-switcher i",this.element).click(function(){var m=$(".dr-month-switcher span",self.element).data("month");var y=$(".dr-year-switcher span",self.element).data("year");var this_moment=moment([y,m,1]);var back=this_moment.clone().subtract(1,"month");var forward=this_moment.clone().add(1,"month").startOf("day");if($(this).hasClass("dr-left")){self.calendarOpen(self.selected,back)}else if($(this).hasClass("dr-right")){self.calendarOpen(self.selected,forward)}});$(".dr-year-switcher i",this.element).click(function(){var m=$(".dr-month-switcher span",self.element).data("month");var y=$(".dr-year-switcher span",self.element).data("year");var this_moment=moment([y,m,1]);var back=this_moment.clone().subtract(1,"year");var forward=this_moment.clone().add(1,"year").startOf("day");if($(this).hasClass("dr-left")){self.calendarOpen(self.selected,back)}else if($(this).hasClass("dr-right")){self.calendarOpen(self.selected,forward)}});$(".dr-dates-dash",this.element).click(function(){$(".dr-date-start",self.element).trigger("click")});var clickHandler=function(event){var contains=$(event.target).parent().closest(self.element);if(!contains.length){document.removeEventListener("click",clickHandler,false);if(self.presetIsOpen)self.presetToggle();if(self.calIsOpen){if($(self.selected).hasClass("dr-date-end"))self.calendarSaveDates();self.calendarSetDates();self.calendarClose("force")}}};this.element.on("click",function(){document.addEventListener("click",clickHandler,false)})}Calendar.prototype.presetToggle=function(){if(this.presetIsOpen==false){this.orig_start_date=this.start_date;this.orig_end_date=this.end_date;this.orig_current_date=this.current_date;this.presetIsOpen=true}else if(this.presetIsOpen){this.presetIsOpen=false}if(this.calIsOpen==true)this.calendarClose();$(".dr-preset-list",this.element).slideToggle(200);$(".dr-input",this.element).toggleClass("dr-active");$(".dr-presets",this.element).toggleClass("dr-active");this.element.toggleClass("dr-active")};Calendar.prototype.presetCreate=function(){var self=this;var ul_presets=$('
');var presets=typeof self.settings.presets==="object"?self.settings.presets:[{label:"Last 30 days",start:moment(self.latest_date).subtract(29,"days"),end:self.latest_date},{label:"Last month",start:moment(self.latest_date).subtract(1,"month").startOf("month"),end:moment(self.latest_date).subtract(1,"month").endOf("month")},{label:"Last 3 months",start:moment(self.latest_date).subtract(3,"month").startOf("month"),end:moment(self.latest_date).subtract(1,"month").endOf("month")},{label:"Last 6 months",start:moment(self.latest_date).subtract(6,"month").startOf("month"),end:moment(self.latest_date).subtract(1,"month").endOf("month")},{label:"Last year",start:moment(self.latest_date).subtract(1,"year").startOf("year"),end:moment(self.latest_date).subtract(1,"year").endOf("year")},{label:"All time",start:self.earliest_date,end:self.latest_date}];if(moment(self.latest_date).diff(moment(self.latest_date).startOf("month"),"days")>=6&&typeof self.settings.presets!=="object"){presets.splice(1,0,{label:"This month",start:moment(self.latest_date).startOf("month"),end:self.latest_date})}$.each(presets,function(i,d){if(moment(d.start).isBefore(self.earliest_date)){d.start=self.earliest_date}if(moment(d.start).isAfter(self.latest_date)){d.start=self.latest_date}if(moment(d.end).isBefore(self.earliest_date)){d.end=self.earliest_date}if(moment(d.end).isAfter(self.latest_date)){d.end=self.latest_date}var startISO=moment(d.start).toISOString();var endISO=moment(d.end).toISOString();var string=moment(d.start).format(self.format.preset)+" – "+moment(d.end).format(self.format.preset);if($(".dr-preset-list",self.element).length){var item=$(".dr-preset-list .dr-list-item:nth-of-type("+(i+1)+") .dr-item-aside",self.element);item.data("start",startISO);item.data("end",endISO);item.html(string)}else{ul_presets.append(''+d.label+''+string+" "+" ")}});return ul_presets};Calendar.prototype.calendarSetDates=function(){$(".dr-date-start",this.element).html(moment(this.start_date).format(this.format.input));$(".dr-date-end",this.element).html(moment(this.end_date).format(this.format.input));if(!this.start_date&&!this.end_date){var old_date=$(".dr-date",this.element).html();var new_date=moment(this.current_date).format(this.format.input);if(old_date.length===0&&!this.required)new_date="";if(old_date!=new_date)$(".dr-date",this.element).html(new_date)}};Calendar.prototype.calendarSaveDates=function(){if(this.type==="double"){if(!moment(this.orig_end_date).isSame(this.end_date)||!moment(this.orig_start_date).isSame(this.start_date))return this.callback()}else{if(!this.required||!moment(this.orig_current_date).isSame(this.current_date))return this.callback()}};Calendar.prototype.calendarCheckDate=function(d){if(d==="today"||d==="now")return moment().isAfter(this.latest_date)?this.latest_date:moment().isBefore(this.earliest_date)?this.earliest_date:moment();if(d==="earliest")return this.earliest_date;if(d==="latest")return this.latest_date;if(d&&(/\bago\b/.test(d)||/\bahead\b/.test(d)))return this.stringToDate(d);var regex=/(?:\d)((?:st|nd|rd|th)?,?)/;var d_array=d?d.replace(regex,"").split(" "):[];if(d_array.length==2){d_array.push(moment().format(this.format.jump_year));d=d_array.join(" ")}var parsed_d=this.parseDate(d);if(!parsed_d.isValid())return moment(d);return parsed_d};Calendar.prototype.calendarCheckDates=function(){var startTxt=$(".dr-date-start",this.element).html();var endTxt=$(".dr-date-end",this.element).html();var c=this.calendarCheckDate($(this.selected).html());var s;var e;if(startTxt==="ytd"||endTxt==="ytd"){s=moment().startOf("year");e=moment().endOf("year")}else{s=this.calendarCheckDate(startTxt);e=this.calendarCheckDate(endTxt)}if(c.isBefore(this.earliest_date))c=this.earliest_date;if(s.isBefore(this.earliest_date))s=this.earliest_date;if(e.isBefore(this.earliest_date)||e.isBefore(s))e=s.clone().add(6,"day");if(c.isAfter(this.latest_date))c=this.latest_date;if(e.isAfter(this.latest_date))e=this.latest_date;if(s.isAfter(this.latest_date)||s.isAfter(e))s=e.clone().subtract(6,"day");if(this.type==="double"){if(s.isSame(e)&&!this.sameDayRange)return this.calendarSetDates();this.start_date=s.isValid()?s:this.start_date;this.end_date=e.isValid()?e:this.end_date}this.current_date=c.isValid()?c:this.current_date};Calendar.prototype.stringToDate=function(str){var date_arr=str.split(" ");if(date_arr[2]==="ago"){return moment(this.current_date).subtract(date_arr[0],date_arr[1])}else if(date_arr[2]==="ahead"){return moment(this.current_date).add(date_arr[0],date_arr[1])}return this.current_date};Calendar.prototype.calendarOpen=function(selected,switcher){var self=this;var other;var cal_width=$(".dr-dates",this.element).innerWidth()-8;this.selected=selected||this.selected;if(this.presetIsOpen==true)this.presetToggle();if(this.calIsOpen==true){this.calendarClose(switcher?"switcher":undefined)}else if($(this.selected).html().length){this.orig_start_date=this.start_date;this.orig_end_date=this.end_date;this.orig_current_date=this.current_date}this.calendarCheckDates();this.calendarCreate(switcher);this.calendarSetDates();var next_month=moment(switcher||this.current_date).add(1,"month").startOf("month").startOf("day");var past_month=moment(switcher||this.current_date).subtract(1,"month").endOf("month");var next_year=moment(switcher||this.current_date).add(1,"year").startOf("month").startOf("day");var past_year=moment(switcher||this.current_date).subtract(1,"year").endOf("month");var this_moment=moment(switcher||this.current_date);$(".dr-month-switcher span",this.element).data("month",this_moment.month()).html(this_moment.format(this.format.jump_month));$(".dr-year-switcher span",this.element).data("year",this_moment.year()).html(this_moment.format(this.format.jump_year));$(".dr-switcher i",this.element).removeClass("dr-disabled");if(next_month.isAfter(this.latest_date))$(".dr-month-switcher .dr-right",this.element).addClass("dr-disabled");if(past_month.isBefore(this.earliest_date))$(".dr-month-switcher .dr-left",this.element).addClass("dr-disabled");if(next_year.isAfter(this.latest_date))$(".dr-year-switcher .dr-right",this.element).addClass("dr-disabled");if(past_year.isBefore(this.earliest_date))$(".dr-year-switcher .dr-left",this.element).addClass("dr-disabled");$(".dr-day",this.element).on({mouseenter:function(){var selected=$(this);var start_date=moment(self.start_date);var end_date=moment(self.end_date);var current_date=moment(self.current_date);if($(self.selected).hasClass("dr-date-start")){selected.addClass("dr-hover dr-hover-before");$(".dr-start",self.element).css({border:"none","padding-left":"0.3125rem"});setMaybeRange("start")}if($(self.selected).hasClass("dr-date-end")){selected.addClass("dr-hover dr-hover-after");$(".dr-end",self.element).css({border:"none","padding-right":"0.3125rem"});setMaybeRange("end")}if(!self.start_date&&!self.end_date)selected.addClass("dr-maybe");$(".dr-selected",self.element).css("background-color","transparent");function setMaybeRange(type){other=undefined;self.range(6*7).forEach(function(i){var next=selected.next().data("date");var prev=selected.prev().data("date");var curr=selected.data("date");if(!curr)return false;if(!prev)prev=curr;if(!next)next=curr;if(type=="start"){if(moment(next).isSame(self.end_date)||self.sameDayRange&&moment(curr).isSame(self.end_date))return false;if(moment(curr).isAfter(self.end_date)){other=other||moment(curr).add(6,"day").startOf("day");if(i>5||(next?moment(next).isAfter(self.latest_date):false)){$(selected).addClass("dr-end");other=moment(curr);return false}}selected=selected.next().addClass("dr-maybe")}else if(type=="end"){if(moment(prev).isSame(self.start_date)||self.sameDayRange&&moment(curr).isSame(self.start_date))return false;if(moment(curr).isBefore(self.start_date)){other=other||moment(curr).subtract(6,"day");if(i>5||(prev?moment(prev).isBefore(self.earliest_date):false)){$(selected).addClass("dr-start");other=moment(curr);return false}}selected=selected.prev().addClass("dr-maybe")}})}},mouseleave:function(){if($(this).hasClass("dr-hover-before dr-end"))$(this).removeClass("dr-end");if($(this).hasClass("dr-hover-after dr-start"))$(this).removeClass("dr-start");$(this).removeClass("dr-hover dr-hover-before dr-hover-after");$(".dr-start, .dr-end",self.element).css({border:"",padding:""});$(".dr-maybe:not(.dr-current)",self.element).removeClass("dr-start dr-end");$(".dr-day",self.element).removeClass("dr-maybe");$(".dr-selected",self.element).css("background-color","")}});if(/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream){$(".dr-day",this.element).on({touchstart:function(){self.selectOneDate(other,self,$(this).data("date"))}});$("div[contenteditable]",this.element).removeAttr("contenteditable")}else{$(".dr-day",this.element).on({mousedown:function(){self.selectOneDate(other,self,$(this).data("date"))}})}$(".dr-calendar",this.element).css("width",cal_width).slideDown(200);$(".dr-input",this.element).addClass("dr-active");$(selected).addClass("dr-active").focus();this.element.addClass("dr-active");this.calIsOpen=true};Calendar.prototype.calendarClose=function(type){var self=this;if(!this.calIsOpen||this.presetIsOpen||type=="force"){$(".dr-calendar",this.element).slideUp(200,function(){$(".dr-day",self.element).remove()})}else{$(".dr-day",this.element).remove()}if(type=="switcher"){return false}$(".dr-input, .dr-date",this.element).removeClass("dr-active");this.element.removeClass("dr-active");this.calIsOpen=false};Calendar.prototype.calendarCreate=function(switcher){var self=this;var array=this.calendarArray(this.start_date,this.end_date,this.current_date,switcher);array.forEach(function(d,i){var classString="dr-day";if(d.fade)classString+=" dr-fade";if(d.start)classString+=" dr-start";if(d.end)classString+=" dr-end";if(d.current)classString+=" dr-current";if(d.selected)classString+=" dr-selected";if(d.outside)classString+=" dr-outside";$(".dr-day-list",self.element).append(''+d.str+" ")})};Calendar.prototype.calendarArray=function(start,end,current,switcher){var self=this;current=moment(current||start||end).startOf("day");var reference=switcher||current||start||end;var startRange=moment(reference).startOf("month").startOf("week");var endRange=moment(startRange).add(6*7-1,"days").endOf("day");var daysInRange=[];var d=moment(startRange);while(d.isBefore(endRange)){daysInRange.push({str:+d.format("D"),start:start&&d.isSame(start,"day"),end:end&&d.isSame(end,"day"),current:current&&d.isSame(current,"day"),selected:start&&end&&d.isBetween(start,end),date:d.toISOString(),outside:d.isBefore(self.earliest_date)||d.isAfter(self.latest_date),fade:!d.isSame(reference,"month")});d.add(1,"d")}return daysInRange};Calendar.prototype.calendarHTML=function(type){var ul_days_of_the_week=$('');var days=this.days_array.splice(moment.localeData().firstDayOfWeek()).concat(this.days_array.splice(0,moment.localeData().firstDayOfWeek()));$.each(days,function(i,elem){ul_days_of_the_week.append(''+elem+" ")});if(type=="double")return this.element.append('"+''+'
'+'
'+'
'+' '+"April "+' '+"
"+'
'+' '+"2015 "+' '+"
"+"
"+ul_days_of_the_week[0].outerHTML+'
'+"
"+(this.presets?this.presetCreate()[0].outerHTML:"")+"
");return this.element.append('"+''+'
'+'
'+'
'+' '+" "+' '+"
"+'
'+' '+" "+' '+"
"+"
"+ul_days_of_the_week[0].outerHTML+'
'+"
"+"
")};Calendar.prototype.parseDate=function(d){if(moment.defaultZone!==null&&moment.hasOwnProperty("tz")){return moment.tz(d,this.format.input,moment.defaultZone.name)}else{return moment(d,this.format.input)}};Calendar.prototype.range=function(length){var range=new Array(length);for(var idx=0;idx=0;i--){attr=toNodeAttrs[i];attrName=attr.name;attrNamespaceURI=attr.namespaceURI;attrValue=attr.value;if(attrNamespaceURI){attrName=attr.localName||attrName;fromValue=fromNode.getAttributeNS(attrNamespaceURI,attrName);if(fromValue!==attrValue){if(attr.prefix==="xmlns"){attrName=attr.name}fromNode.setAttributeNS(attrNamespaceURI,attrName,attrValue)}}else{fromValue=fromNode.getAttribute(attrName);if(fromValue!==attrValue){fromNode.setAttribute(attrName,attrValue)}}}var fromNodeAttrs=fromNode.attributes;for(var d=fromNodeAttrs.length-1;d>=0;d--){attr=fromNodeAttrs[d];attrName=attr.name;attrNamespaceURI=attr.namespaceURI;if(attrNamespaceURI){attrName=attr.localName||attrName;if(!toNode.hasAttributeNS(attrNamespaceURI,attrName)){fromNode.removeAttributeNS(attrNamespaceURI,attrName)}}else{if(!toNode.hasAttribute(attrName)){fromNode.removeAttribute(attrName)}}}}var range;var NS_XHTML="http://www.w3.org/1999/xhtml";var doc=typeof document==="undefined"?undefined:document;var HAS_TEMPLATE_SUPPORT=!!doc&&"content"in doc.createElement("template");var HAS_RANGE_SUPPORT=!!doc&&doc.createRange&&"createContextualFragment"in doc.createRange();function createFragmentFromTemplate(str){var template=doc.createElement("template");template.innerHTML=str;return template.content.childNodes[0]}function createFragmentFromRange(str){if(!range){range=doc.createRange();range.selectNode(doc.body)}var fragment=range.createContextualFragment(str);return fragment.childNodes[0]}function createFragmentFromWrap(str){var fragment=doc.createElement("body");fragment.innerHTML=str;return fragment.childNodes[0]}function toElement(str){str=str.trim();if(HAS_TEMPLATE_SUPPORT){return createFragmentFromTemplate(str)}else if(HAS_RANGE_SUPPORT){return createFragmentFromRange(str)}return createFragmentFromWrap(str)}function compareNodeNames(fromEl,toEl){var fromNodeName=fromEl.nodeName;var toNodeName=toEl.nodeName;var fromCodeStart,toCodeStart;if(fromNodeName===toNodeName){return true}fromCodeStart=fromNodeName.charCodeAt(0);toCodeStart=toNodeName.charCodeAt(0);if(fromCodeStart<=90&&toCodeStart>=97){return fromNodeName===toNodeName.toUpperCase()}else if(toCodeStart<=90&&fromCodeStart>=97){return toNodeName===fromNodeName.toUpperCase()}else{return false}}function createElementNS(name,namespaceURI){return!namespaceURI||namespaceURI===NS_XHTML?doc.createElement(name):doc.createElementNS(namespaceURI,name)}function moveChildren(fromEl,toEl){var curChild=fromEl.firstChild;while(curChild){var nextChild=curChild.nextSibling;toEl.appendChild(curChild);curChild=nextChild}return toEl}function syncBooleanAttrProp(fromEl,toEl,name){if(fromEl[name]!==toEl[name]){fromEl[name]=toEl[name];if(fromEl[name]){fromEl.setAttribute(name,"")}else{fromEl.removeAttribute(name)}}}var specialElHandlers={OPTION:function(fromEl,toEl){var parentNode=fromEl.parentNode;if(parentNode){var parentName=parentNode.nodeName.toUpperCase();if(parentName==="OPTGROUP"){parentNode=parentNode.parentNode;parentName=parentNode&&parentNode.nodeName.toUpperCase()}if(parentName==="SELECT"&&!parentNode.hasAttribute("multiple")){if(fromEl.hasAttribute("selected")&&!toEl.selected){fromEl.setAttribute("selected","selected");fromEl.removeAttribute("selected")}parentNode.selectedIndex=-1}}syncBooleanAttrProp(fromEl,toEl,"selected")},INPUT:function(fromEl,toEl){syncBooleanAttrProp(fromEl,toEl,"checked");syncBooleanAttrProp(fromEl,toEl,"disabled");if(fromEl.value!==toEl.value){fromEl.value=toEl.value}if(!toEl.hasAttribute("value")){fromEl.removeAttribute("value")}},TEXTAREA:function(fromEl,toEl){var newValue=toEl.value;if(fromEl.value!==newValue){fromEl.value=newValue}var firstChild=fromEl.firstChild;if(firstChild){var oldValue=firstChild.nodeValue;if(oldValue==newValue||!newValue&&oldValue==fromEl.placeholder){return}firstChild.nodeValue=newValue}},SELECT:function(fromEl,toEl){if(!toEl.hasAttribute("multiple")){var selectedIndex=-1;var i=0;var curChild=fromEl.firstChild;var optgroup;var nodeName;while(curChild){nodeName=curChild.nodeName&&curChild.nodeName.toUpperCase();if(nodeName==="OPTGROUP"){optgroup=curChild;curChild=optgroup.firstChild}else{if(nodeName==="OPTION"){if(curChild.hasAttribute("selected")){selectedIndex=i;break}i++}curChild=curChild.nextSibling;if(!curChild&&optgroup){curChild=optgroup.nextSibling;optgroup=null}}}fromEl.selectedIndex=selectedIndex}}};var ELEMENT_NODE=1;var DOCUMENT_FRAGMENT_NODE$1=11;var TEXT_NODE=3;var COMMENT_NODE=8;function noop(){}function defaultGetNodeKey(node){if(node){return node.getAttribute&&node.getAttribute("id")||node.id}}function morphdomFactory(morphAttrs){return function morphdom(fromNode,toNode,options){if(!options){options={}}if(typeof toNode==="string"){if(fromNode.nodeName==="#document"||fromNode.nodeName==="HTML"||fromNode.nodeName==="BODY"){var toNodeHtml=toNode;toNode=doc.createElement("html");toNode.innerHTML=toNodeHtml}else{toNode=toElement(toNode)}}else if(toNode.nodeType===DOCUMENT_FRAGMENT_NODE$1){toNode=toNode.firstElementChild}var getNodeKey=options.getNodeKey||defaultGetNodeKey;var onBeforeNodeAdded=options.onBeforeNodeAdded||noop;var onNodeAdded=options.onNodeAdded||noop;var onBeforeElUpdated=options.onBeforeElUpdated||noop;var onElUpdated=options.onElUpdated||noop;var onBeforeNodeDiscarded=options.onBeforeNodeDiscarded||noop;var onNodeDiscarded=options.onNodeDiscarded||noop;var onBeforeElChildrenUpdated=options.onBeforeElChildrenUpdated||noop;var skipFromChildren=options.skipFromChildren||noop;var addChild=options.addChild||function(parent,child){return parent.appendChild(child)};var childrenOnly=options.childrenOnly===true;var fromNodesLookup=Object.create(null);var keyedRemovalList=[];function addKeyedRemoval(key){keyedRemovalList.push(key)}function walkDiscardedChildNodes(node,skipKeyedNodes){if(node.nodeType===ELEMENT_NODE){var curChild=node.firstChild;while(curChild){var key=undefined;if(skipKeyedNodes&&(key=getNodeKey(curChild))){addKeyedRemoval(key)}else{onNodeDiscarded(curChild);if(curChild.firstChild){walkDiscardedChildNodes(curChild,skipKeyedNodes)}}curChild=curChild.nextSibling}}}function removeNode(node,parentNode,skipKeyedNodes){if(onBeforeNodeDiscarded(node)===false){return}if(parentNode){parentNode.removeChild(node)}onNodeDiscarded(node);walkDiscardedChildNodes(node,skipKeyedNodes)}function indexTree(node){if(node.nodeType===ELEMENT_NODE||node.nodeType===DOCUMENT_FRAGMENT_NODE$1){var curChild=node.firstChild;while(curChild){var key=getNodeKey(curChild);if(key){fromNodesLookup[key]=curChild}indexTree(curChild);curChild=curChild.nextSibling}}}indexTree(fromNode);function handleNodeAdded(el){onNodeAdded(el);var curChild=el.firstChild;while(curChild){var nextSibling=curChild.nextSibling;var key=getNodeKey(curChild);if(key){var unmatchedFromEl=fromNodesLookup[key];if(unmatchedFromEl&&compareNodeNames(curChild,unmatchedFromEl)){curChild.parentNode.replaceChild(unmatchedFromEl,curChild);morphEl(unmatchedFromEl,curChild)}else{handleNodeAdded(curChild)}}else{handleNodeAdded(curChild)}curChild=nextSibling}}function cleanupFromEl(fromEl,curFromNodeChild,curFromNodeKey){while(curFromNodeChild){var fromNextSibling=curFromNodeChild.nextSibling;if(curFromNodeKey=getNodeKey(curFromNodeChild)){addKeyedRemoval(curFromNodeKey)}else{removeNode(curFromNodeChild,fromEl,true)}curFromNodeChild=fromNextSibling}}function morphEl(fromEl,toEl,childrenOnly){var toElKey=getNodeKey(toEl);if(toElKey){delete fromNodesLookup[toElKey]}if(!childrenOnly){if(onBeforeElUpdated(fromEl,toEl)===false){return}morphAttrs(fromEl,toEl);onElUpdated(fromEl);if(onBeforeElChildrenUpdated(fromEl,toEl)===false){return}}if(fromEl.nodeName!=="TEXTAREA"){morphChildren(fromEl,toEl)}else{specialElHandlers.TEXTAREA(fromEl,toEl)}}function morphChildren(fromEl,toEl){var skipFrom=skipFromChildren(fromEl);var curToNodeChild=toEl.firstChild;var curFromNodeChild=fromEl.firstChild;var curToNodeKey;var curFromNodeKey;var fromNextSibling;var toNextSibling;var matchingFromEl;outer:while(curToNodeChild){toNextSibling=curToNodeChild.nextSibling;curToNodeKey=getNodeKey(curToNodeChild);while(!skipFrom&&curFromNodeChild){fromNextSibling=curFromNodeChild.nextSibling;if(curToNodeChild.isSameNode&&curToNodeChild.isSameNode(curFromNodeChild)){curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling;continue outer}curFromNodeKey=getNodeKey(curFromNodeChild);var curFromNodeType=curFromNodeChild.nodeType;var isCompatible=undefined;if(curFromNodeType===curToNodeChild.nodeType){if(curFromNodeType===ELEMENT_NODE){if(curToNodeKey){if(curToNodeKey!==curFromNodeKey){if(matchingFromEl=fromNodesLookup[curToNodeKey]){if(fromNextSibling===matchingFromEl){isCompatible=false}else{fromEl.insertBefore(matchingFromEl,curFromNodeChild);if(curFromNodeKey){addKeyedRemoval(curFromNodeKey)}else{removeNode(curFromNodeChild,fromEl,true)}curFromNodeChild=matchingFromEl}}else{isCompatible=false}}}else if(curFromNodeKey){isCompatible=false}isCompatible=isCompatible!==false&&compareNodeNames(curFromNodeChild,curToNodeChild);if(isCompatible){morphEl(curFromNodeChild,curToNodeChild)}}else if(curFromNodeType===TEXT_NODE||curFromNodeType==COMMENT_NODE){isCompatible=true;if(curFromNodeChild.nodeValue!==curToNodeChild.nodeValue){curFromNodeChild.nodeValue=curToNodeChild.nodeValue}}}if(isCompatible){curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling;continue outer}if(curFromNodeKey){addKeyedRemoval(curFromNodeKey)}else{removeNode(curFromNodeChild,fromEl,true)}curFromNodeChild=fromNextSibling}if(curToNodeKey&&(matchingFromEl=fromNodesLookup[curToNodeKey])&&compareNodeNames(matchingFromEl,curToNodeChild)){if(!skipFrom){addChild(fromEl,matchingFromEl)}morphEl(matchingFromEl,curToNodeChild)}else{var onBeforeNodeAddedResult=onBeforeNodeAdded(curToNodeChild);if(onBeforeNodeAddedResult!==false){if(onBeforeNodeAddedResult){curToNodeChild=onBeforeNodeAddedResult}if(curToNodeChild.actualize){curToNodeChild=curToNodeChild.actualize(fromEl.ownerDocument||doc)}addChild(fromEl,curToNodeChild);handleNodeAdded(curToNodeChild)}}curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling}cleanupFromEl(fromEl,curFromNodeChild,curFromNodeKey);var specialElHandler=specialElHandlers[fromEl.nodeName];if(specialElHandler){specialElHandler(fromEl,toEl)}}var morphedNode=fromNode;var morphedNodeType=morphedNode.nodeType;var toNodeType=toNode.nodeType;if(!childrenOnly){if(morphedNodeType===ELEMENT_NODE){if(toNodeType===ELEMENT_NODE){if(!compareNodeNames(fromNode,toNode)){onNodeDiscarded(fromNode);morphedNode=moveChildren(fromNode,createElementNS(toNode.nodeName,toNode.namespaceURI))}}else{morphedNode=toNode}}else if(morphedNodeType===TEXT_NODE||morphedNodeType===COMMENT_NODE){if(toNodeType===morphedNodeType){if(morphedNode.nodeValue!==toNode.nodeValue){morphedNode.nodeValue=toNode.nodeValue}return morphedNode}else{morphedNode=toNode}}}if(morphedNode===toNode){onNodeDiscarded(fromNode)}else{if(toNode.isSameNode&&toNode.isSameNode(morphedNode)){return}morphEl(morphedNode,toNode,childrenOnly);if(keyedRemovalList){for(var i=0,len=keyedRemovalList.length;i {
2 |
3 | /**
4 | *
5 | * @param string
6 | * @return {boolean}
7 | */
8 | function isString (string) {
9 | return typeof string === 'string'
10 | }
11 |
12 | const AttributeHandlers = {
13 | value: ( el, value ) => {
14 | el.value = value
15 | },
16 | className: (el, attribute) => {
17 | if (isString(attribute)) {
18 | attribute = attribute.split(' ').map( c => c.trim() ).filter( c => c )
19 | }
20 |
21 | el.classList.add(...attribute)
22 | },
23 | eventHandlers: (el, events) => {
24 | for (let event in events) {
25 | el.addEventListener(event, events[event])
26 | }
27 | },
28 | onInput: (el, func) => AttributeHandlers.eventHandlers(el, { input: func }),
29 | onChange: (el, func) => AttributeHandlers.eventHandlers(el, { change: func }),
30 | onFocus: (el, func) => AttributeHandlers.eventHandlers(el, { focus: func }),
31 | onClick: (el, func) => AttributeHandlers.eventHandlers(el, { click: func }),
32 | style: (el, style) => {
33 |
34 | if (isString(style)) {
35 | el.style = style
36 | return
37 | }
38 |
39 | for (let attribute in style) {
40 | el.style[attribute] = style[attribute]
41 | }
42 | },
43 | onCreate: (el, func) => func(el),
44 |
45 | }
46 |
47 | /**
48 | *
49 | * @param html
50 | * @return {ChildNode}
51 | */
52 | function htmlToElement (html) {
53 | var template = document.createElement('template')
54 | html = html.trim() // Never return a text node of whitespace as the result
55 | template.innerHTML = html
56 | return template.content.firstChild
57 | }
58 |
59 | /**
60 | *
61 | * @param html
62 | * @return {NodeListOf}
63 | */
64 | function htmlToElements (html) {
65 | var template = document.createElement('template')
66 | template.innerHTML = html
67 | return template.content.childNodes
68 | }
69 |
70 | /**
71 | *
72 | * @param tagName
73 | * @param attributes
74 | * @param children
75 | * @return {*}
76 | */
77 | const makeEl = (tagName, attributes, children = null) => {
78 |
79 | let el = tagName === 'fragment' ? document.createDocumentFragment() : document.createElement(tagName)
80 |
81 | for (let attributeName in attributes) {
82 |
83 | if (attributes[attributeName] === false) {
84 | continue
85 | }
86 |
87 | if (AttributeHandlers.hasOwnProperty(attributeName)) {
88 | AttributeHandlers[attributeName](el, attributes[attributeName])
89 | continue
90 | }
91 |
92 | if (attributeName.startsWith('data')) {
93 | let dataName = attributeName.replace(/^data(.+)/, '$1')
94 | dataName = dataName.charAt(0).toLowerCase() + dataName.slice(1)
95 |
96 | el.dataset[dataName] = attributes[attributeName]
97 | continue
98 | }
99 |
100 | el.setAttribute(attributeName, attributes[attributeName])
101 | }
102 |
103 | if (children === null) {
104 | return el
105 | }
106 |
107 | if (!Array.isArray(children)) {
108 | children = [children]
109 | }
110 |
111 | children.forEach(child => {
112 |
113 | if (! child) {
114 | return
115 | }
116 |
117 | // Template literals
118 | if (isString(child)) {
119 | let _children = htmlToElements(child)
120 | while (_children.length) {
121 | el.appendChild(_children[0])
122 | }
123 | return
124 | }
125 |
126 | el.appendChild(child)
127 | })
128 |
129 | return el
130 | }
131 |
132 | const Input = (attributes) => {
133 | return makeEl('input', {
134 | type: 'text',
135 | ...attributes,
136 | })
137 | }
138 |
139 | const Textarea = (attributes) => {
140 | return makeEl('textarea', {
141 | ...attributes,
142 | })
143 | }
144 |
145 | const Select = (attributes) => {
146 |
147 | let {
148 | options = {},
149 | selected = '',
150 | onChange = e => {},
151 | ...rest
152 | } = attributes
153 |
154 | if (!Array.isArray(options)) {
155 | options = Object.keys(options).map(key => ({ value: key, text: options[key] }))
156 | }
157 |
158 | if (!Array.isArray(selected)) {
159 | selected = [selected]
160 | }
161 |
162 | options = options.map(opt => typeof opt === 'string' ? { value: opt, text: opt } : opt).
163 | map(({ value, text }) => makeEl('option', {
164 | value,
165 | selected: selected.includes(value),
166 | }, text))
167 |
168 | return makeEl('select', {
169 | ...rest,
170 | onChange: (e) => {
171 | if (rest.multiple) {
172 | e.target.values = e.target.querySelectorAll('option:checked').map(el => el.value)
173 | }
174 |
175 | onChange(e)
176 | },
177 | }, options)
178 | }
179 |
180 | const Button = (attributes, children) => {
181 | return makeEl('button', {
182 | ...attributes,
183 | }, children)
184 | }
185 |
186 | const Toggle = ({
187 | onLabel = 'On',
188 | offLabel = 'Off',
189 | ...atts
190 | }) => {
191 |
192 | return makeEl('label', {
193 | className: 'holler-switch',
194 | }, [
195 | Input({
196 | ...atts,
197 | type: 'checkbox',
198 | }),
199 | //language=HTML
200 | `
201 | ${onLabel}
202 | ${offLabel} `,
203 | ])
204 | }
205 |
206 | const Div = (attributes = {}, children = []) => {
207 | return makeEl('div', attributes, children)
208 | }
209 |
210 | const Dashicon = (icon) => {
211 | return makeEl('span', {
212 | className: `dashicons dashicons-${icon}`,
213 | })
214 | }
215 |
216 | const Fragment = ( children ) => {
217 | return makeEl( 'fragment', {}, children )
218 | }
219 |
220 | const Span = (attributes = {}, children = []) => {
221 | return makeEl('span', attributes, children )
222 | }
223 |
224 | const Label = (attributes = {}, children = []) => {
225 | return makeEl('label', attributes, children )
226 | }
227 |
228 | const InputRepeater = ({
229 | onChange = () => {},
230 | rows = [],
231 | cells = [],
232 | sortable = false,
233 | fillRow = () => Array(cells.length).fill(''),
234 | }) => {
235 |
236 | const changeEvent = () => new CustomEvent()
237 |
238 | const removeRow = (rowIndex) => {
239 | rows.splice(rowIndex, 1)
240 | onChange(rows)
241 | }
242 |
243 | const addRow = () => {
244 | rows.push(fillRow())
245 | onChange(rows)
246 | }
247 |
248 | const onCellChange = (rowIndex, cellIndex, value) => {
249 | rows[rowIndex][cellIndex] = value
250 | onChange(rows)
251 | }
252 |
253 | const RepeaterRow = (row, rowIndex) => Div({
254 | className: 'holler-input-repeater-row',
255 | dataRow: rowIndex,
256 | }, [
257 | // Cells
258 | ...cells.map((cellCallback, cellIndex) => cellCallback({
259 | value: row[cellIndex] ?? '',
260 | dataRow: rowIndex,
261 | dataCell: cellIndex,
262 | onChange: e => onCellChange(rowIndex, cellIndex, e.target.value),
263 | }, row)),
264 | // Sortable Handle
265 | sortable ? makeEl('span', {
266 | className: 'handle',
267 | dataRow: rowIndex,
268 | }, Dashicon('move')) : null,
269 | // Remove Row Button
270 | Button({
271 | className: 'holler-button dashicon remove-row',
272 | dataRow: rowIndex,
273 | onClick: e => removeRow(rowIndex),
274 | }, Dashicon('no-alt')),
275 | ])
276 |
277 | let repeater = Div({
278 | className: 'holler-input-repeater',
279 | onCreate: el => {
280 |
281 | if (!sortable) {
282 | return
283 | }
284 |
285 | $(el).sortable({
286 | handle: '.handle',
287 | update: (e, ui) => {
288 |
289 | let $row = $(ui.item)
290 | let oldIndex = parseInt($row.data('row'))
291 | let curIndex = $row.index()
292 |
293 | let row = rows[oldIndex]
294 |
295 | rows.splice(oldIndex, 1)
296 | rows.splice(curIndex, 0, row)
297 | onChange(rows, repeater)
298 | },
299 | })
300 | },
301 | }, [
302 | ...rows.map((row, i) => RepeaterRow(row, i)),
303 | Div({
304 | className: 'holler-input-repeater-row-add',
305 | }, [
306 | `
`,
307 | // Add Row Button
308 | Button({
309 | className: 'add-row holler-button dashicon',
310 | onClick: e => addRow(),
311 | }, Dashicon('plus-alt2')),
312 | ]),
313 | ])
314 |
315 | return repeater
316 | }
317 |
318 | window.MakeEl = {
319 | makeEl,
320 | Input,
321 | Textarea,
322 | Select,
323 | Button,
324 | Toggle,
325 | Div,
326 | Span,
327 | Label,
328 | InputRepeater,
329 | Fragment
330 | }
331 | })(jQuery)
--------------------------------------------------------------------------------
/assets/js/make-el.min.js:
--------------------------------------------------------------------------------
1 | ($=>{function isString(string){return typeof string==="string"}const AttributeHandlers={value:(el,value)=>{el.value=value},className:(el,attribute)=>{if(isString(attribute)){attribute=attribute.split(" ").map(c=>c.trim()).filter(c=>c)}el.classList.add(...attribute)},eventHandlers:(el,events)=>{for(let event in events){el.addEventListener(event,events[event])}},onInput:(el,func)=>AttributeHandlers.eventHandlers(el,{input:func}),onChange:(el,func)=>AttributeHandlers.eventHandlers(el,{change:func}),onFocus:(el,func)=>AttributeHandlers.eventHandlers(el,{focus:func}),onClick:(el,func)=>AttributeHandlers.eventHandlers(el,{click:func}),style:(el,style)=>{if(isString(style)){el.style=style;return}for(let attribute in style){el.style[attribute]=style[attribute]}},onCreate:(el,func)=>func(el)};function htmlToElement(html){var template=document.createElement("template");html=html.trim();template.innerHTML=html;return template.content.firstChild}function htmlToElements(html){var template=document.createElement("template");template.innerHTML=html;return template.content.childNodes}const makeEl=(tagName,attributes,children=null)=>{let el=tagName==="fragment"?document.createDocumentFragment():document.createElement(tagName);for(let attributeName in attributes){if(attributes[attributeName]===false){continue}if(AttributeHandlers.hasOwnProperty(attributeName)){AttributeHandlers[attributeName](el,attributes[attributeName]);continue}if(attributeName.startsWith("data")){let dataName=attributeName.replace(/^data(.+)/,"$1");dataName=dataName.charAt(0).toLowerCase()+dataName.slice(1);el.dataset[dataName]=attributes[attributeName];continue}el.setAttribute(attributeName,attributes[attributeName])}if(children===null){return el}if(!Array.isArray(children)){children=[children]}children.forEach(child=>{if(!child){return}if(isString(child)){let _children=htmlToElements(child);while(_children.length){el.appendChild(_children[0])}return}el.appendChild(child)});return el};const Input=attributes=>{return makeEl("input",{type:"text",...attributes})};const Textarea=attributes=>{return makeEl("textarea",{...attributes})};const Select=attributes=>{let{options:options={},selected:selected="",onChange:onChange=e=>{},...rest}=attributes;if(!Array.isArray(options)){options=Object.keys(options).map(key=>({value:key,text:options[key]}))}if(!Array.isArray(selected)){selected=[selected]}options=options.map(opt=>typeof opt==="string"?{value:opt,text:opt}:opt).map(({value,text})=>makeEl("option",{value:value,selected:selected.includes(value)},text));return makeEl("select",{...rest,onChange:e=>{if(rest.multiple){e.target.values=e.target.querySelectorAll("option:checked").map(el=>el.value)}onChange(e)}},options)};const Button=(attributes,children)=>{return makeEl("button",{...attributes},children)};const Toggle=({onLabel:onLabel="On",offLabel:offLabel="Off",...atts})=>{return makeEl("label",{className:"holler-switch"},[Input({...atts,type:"checkbox"}),`
2 | ${onLabel}
3 | ${offLabel} `])};const Div=(attributes={},children=[])=>{return makeEl("div",attributes,children)};const Dashicon=icon=>{return makeEl("span",{className:`dashicons dashicons-${icon}`})};const Fragment=children=>{return makeEl("fragment",{},children)};const Span=(attributes={},children=[])=>{return makeEl("span",attributes,children)};const Label=(attributes={},children=[])=>{return makeEl("label",attributes,children)};const InputRepeater=({onChange:onChange=()=>{},rows:rows=[],cells:cells=[],sortable:sortable=false,fillRow:fillRow=()=>Array(cells.length).fill("")})=>{const changeEvent=()=>new CustomEvent;const removeRow=rowIndex=>{rows.splice(rowIndex,1);onChange(rows)};const addRow=()=>{rows.push(fillRow());onChange(rows)};const onCellChange=(rowIndex,cellIndex,value)=>{rows[rowIndex][cellIndex]=value;onChange(rows)};const RepeaterRow=(row,rowIndex)=>Div({className:"holler-input-repeater-row",dataRow:rowIndex},[...cells.map((cellCallback,cellIndex)=>cellCallback({value:row[cellIndex]??"",dataRow:rowIndex,dataCell:cellIndex,onChange:e=>onCellChange(rowIndex,cellIndex,e.target.value)},row)),sortable?makeEl("span",{className:"handle",dataRow:rowIndex},Dashicon("move")):null,Button({className:"holler-button dashicon remove-row",dataRow:rowIndex,onClick:e=>removeRow(rowIndex)},Dashicon("no-alt"))]);let repeater=Div({className:"holler-input-repeater",onCreate:el=>{if(!sortable){return}$(el).sortable({handle:".handle",update:(e,ui)=>{let $row=$(ui.item);let oldIndex=parseInt($row.data("row"));let curIndex=$row.index();let row=rows[oldIndex];rows.splice(oldIndex,1);rows.splice(curIndex,0,row);onChange(rows,repeater)}})}},[...rows.map((row,i)=>RepeaterRow(row,i)),Div({className:"holler-input-repeater-row-add"},[`
`,Button({className:"add-row holler-button dashicon",onClick:e=>addRow()},Dashicon("plus-alt2"))])]);return repeater};window.MakeEl={makeEl:makeEl,Input:Input,Textarea:Textarea,Select:Select,Button:Button,Toggle:Toggle,Div:Div,Span:Span,Label:Label,InputRepeater:InputRepeater,Fragment:Fragment}})(jQuery);
--------------------------------------------------------------------------------
/assets/js/reports.min.js:
--------------------------------------------------------------------------------
1 | ($=>{const{report_data:report_data=[]}=HollerBox;const{icons,confirmationModal,tooltipIcon,tooltip}=HollerBox.elements;const{__}=wp.i18n;let after,before;after=moment().subtract(6,"days");before=moment();const __YMD="YYYY-MM-DD";function ApiError(message){this.name="ApiError";this.message=message}ApiError.prototype=Error.prototype;function darkenRGB(rgb,percentage){const[r,g,b]=rgb.match(/\d+/g).map(Number);const validPercentage=Math.max(0,Math.min(100,percentage));const factor=1-validPercentage/100;const newR=Math.round(r*factor);const newG=Math.round(g*factor);const newB=Math.round(b*factor);return`rgb(${newR}, ${newG}, ${newB})`}async function apiGet(route,params={},opts={}){let __params=new URLSearchParams;Object.keys(params).forEach(k=>{__params.append(k,params[k])});const response=await fetch(route+"?"+__params,{headers:{"X-WP-Nonce":HollerBox.nonces._wprest},...opts});let json=await response.json();if(!response.ok){console.log(json);throw new ApiError(json.message)}return json}function getDatesInRange(after,before){let date=moment(after);const dates=[];while(date<=before){dates.push(moment(date));date.add(1,"day")}return dates}const arrayUnique=items=>{let set=new Set(items);return[...set]};const ReportData={report_data:{},popups:{},cache:{},fetch(){return apiGet(HollerBox.routes.report,{before:before.format(__YMD),after:after.format(__YMD)}).then(r=>{this.report_data=r.data;this.popups=r.popups})},getPopup(id){return this.popups.find(p=>p.ID==id)},getPopups(){return arrayUnique(this.report_data.map(({popup_id})=>parseInt(popup_id))).map(id=>this.popups.find(p=>p.ID==id))},getPopupIds(){return arrayUnique(this.report_data.map(({popup_id})=>parseInt(popup_id)))},getPages(){return arrayUnique(this.report_data.map(({location})=>location))},getContents({popup_id:_popup_id=false}){return arrayUnique(this.report_data.filter(({popup_id,s_type})=>popup_id==_popup_id&&s_type==="conversion").map(({content})=>content))},sumCount(type,{id:id=false,date:date=false,location:_location=false,content:_content=false}){return this.report_data.filter(({popup_id,s_type,s_date,location:location="",content:content=""})=>(id?popup_id==id:true)&&(date?s_date===date.format(__YMD):true)&&(_location?_location===location:true)&&(_content?_content===content:true)&&s_type===type).reduce((total,{s_count})=>total+parseInt(s_count),0)},sumConversions(query){return this.sumCount("conversion",query)},sumImpressions(query){return this.sumCount("impression",query)},sumContent(query){return this.sumCount("conversion",query)}};const{Div,Input,Select,Button}=MakeEl;const Pagination=({rows:rows=[],itemsPerPage:itemsPerPage=10,currentPage:currentPage=1,onPageChange:onPageChange=page=>{}})=>{let numPages=Math.ceil(rows.length/itemsPerPage);const PrevButton=()=>Button({className:"holler-button secondary prev-button",onClick:()=>onPageChange(currentPage-1)},"Prev");const NextButton=()=>Button({className:"holler-button secondary next-button",onClick:()=>onPageChange(currentPage+1)},"Next");const PageButton=page=>Button({className:`holler-button ${currentPage===page?"primary":"secondary"} paginate page-${page}`,onClick:()=>onPageChange(page)},`${page}`);let pageButtons=[];let start=Math.max(1,currentPage-2);let end=Math.min(numPages,start+3);if(start>1){pageButtons.push(PageButton(1));if(start>2){pageButtons.push('… ')}}for(let i=start;i<=end;i++){pageButtons.push(PageButton(i))}if(end…')}pageButtons.push(PageButton(numPages))}return Div({className:"pagination display-flex gap-10"},[currentPage>1?PrevButton():null,...pageButtons,currentPage{}})=>{const $el=$(selector);let itemsPerPage=10;let currentPage=1;const renderTable=()=>{let offSet=(currentPage-1)*itemsPerPage;return`
2 |
3 |
4 | ${headers.map(h=>`${h} `).join("")}
5 |
6 |
7 | ${rows.slice(offSet,offSet+itemsPerPage).map(row=>`${row.map(item=>`${item} `).join("")} `).join("")}
8 |
9 |
10 |
11 | `};const mount=()=>{$el.html(renderTable());if(rows.length>itemsPerPage){morphdom(document.querySelector(`${selector} .table-pagination`),Pagination({rows:rows,itemsPerPage:itemsPerPage,currentPage:currentPage,onPageChange:page=>{currentPage=page;mount()}}))}onMount()};mount()};const lineChart=(id,query={})=>{const dates=getDatesInRange(after,before);const labels=dates.map(m=>m.format("MMM D"));const data={labels:labels,datasets:[{label:"impressions",data:dates.map(date=>ReportData.sumImpressions({date:date,...query})),tension:.1,fill:true,backgroundColor:"rgba(0, 117, 255, 0.20)",borderColor:"rgba(0, 117, 255, 0.25)"},{label:"conversions",data:dates.map(date=>ReportData.sumConversions({date:date,...query})),tension:.1,fill:true,backgroundColor:"rgba(0, 117, 255, 0.70)",borderColor:"rgba(0, 117, 255, 0.80)"}]};const config={type:"line",data:data,options:{maintainAspectRatio:false}};const myChart=new Chart(document.getElementById(id),config)};const pages=[{slug:/popup\/[0-9]+/,render:()=>{return`
12 |
13 |
14 |
15 |
16 |
24 |
32 |
40 |
48 |
55 |
63 | `},onMount:([name,popup_id],setPage)=>{tooltip("#conversion-content",{content:"The content a user interacted with when a conversion was recorded."});let popup=ReportData.getPopup(popup_id);if(!popup){confirmationModal({alert:`${__("There is no data for this popup yet. Wait a few days and check again.")}
`,onConfirm:()=>{setPage("/")}});return}$(".popup-title").html(popup.post_title);$("#edit-popup").on("click",e=>{e.preventDefault();window.open(`${HollerBox.admin_url}/post.php?post=${popup.ID}&action=edit`,"_self")});lineChart("main-graph",{id:popup.ID});let contents=ReportData.getContents({popup_id:popup.ID});let rgb="rgb(0,120,255)";new Chart(document.getElementById("content-graph"),{type:"doughnut",data:{labels:contents.map(c=>c?c:"Clicked"),datasets:[{label:"Conversion Content",data:contents.map(content=>ReportData.sumContent({content:content,id:popup.ID})),backgroundColor:contents.map((c,i)=>{if(i>0){rgb=darkenRGB(rgb,20)}return rgb})}]},options:{plugins:{legend:{position:"right"}},aspectRatio:2}});let impressions=ReportData.sumImpressions({id:popup.ID});let conversions=ReportData.sumConversions({id:popup.ID});$("#impressions").html(impressions);$("#conversions").html(conversions);$("#conversion-rate").html(Math.floor(conversions/Math.max(impressions,1)*100)+"%");Table("#pages-table",{headers:["Page","Imp.","Conv.","CVR."],rows:ReportData.getPages().map(page=>{let impressions=ReportData.sumImpressions({location:page,id:popup.ID});let conversions=ReportData.sumConversions({location:page,id:popup.ID});return[`${page} `,impressions,conversions,Math.floor(conversions/Math.max(impressions,1)*100)+"%"]}).filter(([link,impressions])=>impressions>0).sort(([la,ia,ca],[lb,ib,cb])=>{if(ca===cb){return ib-ia}return cb-ca})})}},{slug:"",render:()=>{return`
64 |
72 |
80 |
88 |
96 |
97 |
100 |
102 |
103 |
110 | `},onMount:(params,setPage)=>{lineChart("main-graph",{});let impressions=ReportData.sumImpressions({});let conversions=ReportData.sumConversions({});$("#impressions").html(impressions);$("#conversions").html(conversions);$("#conversion-rate").html(Math.floor(conversions/Math.max(impressions,1)*100)+"%");Table("#pages-table",{headers:["Page","Imp.","Conv.","CVR."],rows:ReportData.getPages().map(page=>{let impressions=ReportData.sumImpressions({location:page});let conversions=ReportData.sumConversions({location:page});return[`${page} `,impressions,conversions,Math.floor(conversions/impressions*100)+"%"]}).sort(([la,ia,ca],[lb,ib,cb])=>{if(ca===cb){return ib-ia}return cb-ca})});Table("#popups-table",{onMount:()=>{$(".popup-link").on("click",e=>{e.preventDefault();setPage(`/popup/${e.target.dataset.id}/`)})},headers:["Popup","Imp.","Conv.","CVR."],rows:ReportData.getPopups().map(p=>{let impressions=ReportData.sumImpressions({id:p.ID});let conversions=ReportData.sumConversions({id:p.ID});return[``,impressions,conversions,Math.floor(conversions/impressions*100)+"%"]}).sort(([la,ia,ca],[lb,ib,cb])=>{if(ca===cb){return ib-ia}return cb-ca})})}}];const Page={slug:"",currentPage:pages[0],params:[],getCurSlug(){return window.location.hash.substring(1)},initFromSlug(){this.slug=this.getCurSlug();this.params=this.getCurSlug().split("/").filter(p=>p);this.mount();window.dispatchEvent(new Event("resize"))},init(){if(window.location.hash){this.initFromSlug()}else{history.pushState({},"",`#/`);this.initFromSlug()}window.addEventListener("popstate",e=>{this.initFromSlug()})},renderReports(){return`
111 |
117 |
118 | ${this.currentPage.render()}
119 |
`},mount(){this.currentPage=pages.find(p=>this.slug.match(p.slug));const setPage=slug=>{history.pushState({},"",`#${slug}`);this.initFromSlug()};$("#holler-app").html(this.renderReports());const datePicker=new Calendar({element:$("#holler-datepicker"),presets:[{label:"Last 30 days",start:moment().subtract(29,"days"),end:moment()},{label:"Last 14 days",start:moment().subtract(13,"days"),end:moment()},{label:"Last 7 days",start:moment().subtract(6,"days"),end:moment()},{label:"Today",start:moment(),end:moment()},{label:"Yesterday",start:moment().subtract(1,"day"),end:moment().subtract(1,"day")},{label:"This month",start:moment().startOf("month"),end:moment().endOf("month")},{label:"Last month",start:moment().subtract(1,"month").startOf("month"),end:moment().subtract(1,"month").endOf("month")}],format:{preset:"MMM D"},earliest_date:"January 1, 2017",latest_date:moment(),start_date:after,end_date:before,callback:function(){after=this.start_date;before=this.end_date;ReportData.fetch().then(()=>Page.mount())}});this.currentPage.onMount(this.params,setPage)}};$(()=>ReportData.fetch().then(()=>Page.init()))})(jQuery);
--------------------------------------------------------------------------------
/holler-box.php:
--------------------------------------------------------------------------------
1 | setup_constants();
60 | $this->includes();
61 | $this->load_textdomain();
62 | $this->hooks();
63 |
64 | Holler_Admin::instance();
65 | new Holler_Api();
66 | new Holler_Frontend();
67 | new Holler_Telemetry();
68 | new Holler_Updater();
69 |
70 | Holler_Licensing::instance();
71 | }
72 |
73 | /**
74 | * Setup plugin constants
75 | *
76 | * @access private
77 | * @since 0.1.0
78 | * @return void
79 | */
80 | private function setup_constants() {
81 |
82 | // Plugin version
83 | define( 'Holler_Box_VER', HOLLERBOX_VERSION );
84 |
85 | // Plugin path
86 | define( 'Holler_Box_DIR', plugin_dir_path( __FILE__ ) );
87 |
88 | // Plugin URL
89 | define( 'Holler_Box_URL', plugin_dir_url( __FILE__ ) );
90 | }
91 |
92 |
93 | /**
94 | * Include necessary files
95 | *
96 | * @access private
97 | * @since 0.1.0
98 | * @return void
99 | */
100 | private function includes() {
101 | require_once __DIR__ . '/includes/class-holler-api.php';
102 | require_once __DIR__ . '/includes/class-holler-admin.php';
103 | require_once __DIR__ . '/includes/class-holler-popup.php';
104 | require_once __DIR__ . '/includes/class-holler-frontend.php';
105 | require_once __DIR__ . '/includes/class-holler-lead.php';
106 | require_once __DIR__ . '/includes/class-holler-integrations.php';
107 | require_once __DIR__ . '/includes/class-holler-reporting.php';
108 | require_once __DIR__ . '/includes/class-holler-settings.php';
109 | require_once __DIR__ . '/includes/class-holler-licensing.php';
110 | require_once __DIR__ . '/includes/class-holler-telemetry.php';
111 | require_once __DIR__ . '/includes/class-holler-updater.php';
112 | require_once __DIR__ . '/includes/Holler_EDD_SL_Plugin_Updater.php';
113 | }
114 |
115 |
116 | /**
117 | * Run action and filter hooks
118 | *
119 | * @access private
120 | * @since 0.1.0
121 | * @return void
122 | *
123 | *
124 | */
125 | private function hooks() {
126 | }
127 |
128 | /**
129 | * Internationalization
130 | *
131 | * @access public
132 | * @since 0.1.0
133 | * @return void
134 | */
135 | public function load_textdomain() {
136 |
137 | load_plugin_textdomain( 'holler-box' );
138 |
139 | }
140 |
141 | }
142 | } // End if class_exists check
143 |
144 |
145 | /**
146 | * The main function responsible for returning the one true EDD_Metrics
147 | * instance to functions everywhere
148 | *
149 | * @since 0.1.0
150 | * @return \Holler_Box The one true Holler_Box
151 | *
152 | */
153 | function holler_box_load() {
154 | Holler_Box::instance();
155 |
156 | do_action( 'hollerbox/loaded' );
157 | }
158 |
159 | add_action( 'plugins_loaded', 'holler_box_load' );
160 |
161 | /**
162 | * The activation hook is called outside of the singleton because WordPress doesn't
163 | * register the call from within the class, since we are preferring the plugins_loaded
164 | * hook for compatibility, we also can't reference a function inside the plugin class
165 | * for the activation function. If you need an activation function, put it here.
166 | *
167 | * @since 0.1.0
168 | * @return void
169 | */
170 | function holler_box_activation() {
171 | /* Activation functions here */
172 |
173 | holler_box_load();
174 |
175 | Holler_Reporting::instance()->create_table();
176 | }
177 |
178 | register_activation_hook( __FILE__, 'holler_box_activation' );
179 |
--------------------------------------------------------------------------------
/includes/class-holler-api.php:
--------------------------------------------------------------------------------
1 | \d+)', [
18 | [
19 | 'methods' => WP_REST_Server::READABLE,
20 | 'callback' => [ $this, 'read' ],
21 | 'permission_callback' => [ $this, 'permission_callback' ]
22 | ],
23 | [
24 | 'methods' => WP_REST_Server::EDITABLE,
25 | 'callback' => [ $this, 'update' ],
26 | 'permission_callback' => [ $this, 'permission_callback' ]
27 | ],
28 | [
29 | 'methods' => WP_REST_Server::DELETABLE,
30 | 'callback' => [ $this, 'delete' ],
31 | 'permission_callback' => [ $this, 'permission_callback' ]
32 | ],
33 | ] );
34 |
35 | register_rest_route( 'hollerbox', 'submit/(?P\d+)', [
36 | [
37 | 'methods' => WP_REST_Server::CREATABLE,
38 | 'callback' => [ $this, 'submit' ],
39 | 'permission_callback' => '__return_true'
40 | ]
41 | ] );
42 |
43 | register_rest_route( 'hollerbox', '/report', [
44 | [
45 | 'methods' => WP_REST_Server::READABLE,
46 | 'callback' => [ $this, 'read_report' ],
47 | 'permission_callback' => [ $this, 'permission_callback' ]
48 | ]
49 | ] );
50 |
51 | register_rest_route( 'hollerbox', 'options', [
52 | [
53 | 'methods' => WP_REST_Server::READABLE,
54 | 'callback' => [ $this, 'read_options' ],
55 | 'permission_callback' => [ $this, 'permission_callback' ]
56 | ]
57 | ] );
58 |
59 | register_rest_route( 'hollerbox', 'closed', [
60 | [
61 | 'methods' => WP_REST_Server::CREATABLE,
62 | 'callback' => [ $this, 'track_popup_closed' ],
63 | 'permission_callback' => 'is_user_logged_in'
64 | ]
65 | ] );
66 |
67 | register_rest_route( 'hollerbox', 'conversion', [
68 | [
69 | 'methods' => WP_REST_Server::CREATABLE,
70 | 'callback' => [ $this, 'track_conversion' ],
71 | 'permission_callback' => '__return_true'
72 | ]
73 | ] );
74 |
75 | register_rest_route( 'hollerbox', 'impression', [
76 | [
77 | 'methods' => WP_REST_Server::CREATABLE,
78 | 'callback' => [ $this, 'track_impression' ],
79 | 'permission_callback' => '__return_true'
80 | ]
81 | ] );
82 |
83 | register_rest_route( 'hollerbox', 'install', [
84 | [
85 | 'methods' => WP_REST_Server::CREATABLE,
86 | 'callback' => [ $this, 'install_plugin' ],
87 | 'permission_callback' => [ $this, 'plugins_permission_callback' ]
88 | ]
89 | ] );
90 |
91 | register_rest_route( 'hollerbox', 'settings', [
92 | [
93 | 'methods' => WP_REST_Server::EDITABLE,
94 | 'callback' => [ $this, 'update_settings' ],
95 | 'permission_callback' => [ $this, 'options_permission_callback' ]
96 | ]
97 | ] );
98 |
99 | register_rest_route( 'hollerbox', 'library', [
100 | [
101 | 'methods' => WP_REST_Server::READABLE,
102 | 'callback' => [ $this, 'library' ],
103 | 'permission_callback' => [ $this, 'permission_callback' ]
104 | ]
105 | ] );
106 | }
107 |
108 | /**
109 | * Do library stuff
110 | *
111 | * @return WP_Error|WP_REST_Response
112 | */
113 | public function library(){
114 |
115 | $response = wp_remote_get( 'https://library.groundhogg.io/wp-json/hollerbox/list/' );
116 |
117 | if ( is_wp_error( $response ) ){
118 | return $response;
119 | }
120 |
121 | $body = wp_remote_retrieve_body( $response );
122 | $json = json_decode( $body );
123 |
124 | return rest_ensure_response( $json );
125 | }
126 |
127 | /**
128 | * Get all report data for specific time rage
129 | *
130 | * @param WP_REST_Request $request
131 | *
132 | * @return WP_Error|WP_HTTP_Response|WP_REST_Response
133 | */
134 | public function read_report( WP_REST_Request $request ) {
135 |
136 | $fallback = new DateTime( '30 days ago', wp_timezone() );
137 |
138 | $before = sanitize_text_field( $request->get_param( 'before' ) ?: current_time( 'Y-m-d' ) );
139 | $after = sanitize_text_field( $request->get_param( 'after' ) ?: $fallback->format( 'Y-m-d' ) );
140 |
141 | $data = Holler_Reporting::instance()->get_report_data( [
142 | 'before' => $before,
143 | 'after' => $after
144 | ] );
145 |
146 | $popups = array_unique( wp_parse_id_list( wp_list_pluck( $data, 'popup_id' ) ) );
147 | $popups = array_map( function ( $id ) {
148 | return new Holler_Popup( $id );
149 | }, $popups );
150 |
151 | return rest_ensure_response( [
152 | 'data' => $data,
153 | 'popups' => array_values( $popups ),
154 | ] );
155 | }
156 |
157 | /**
158 | * When a popup is closed
159 | *
160 | * @param WP_REST_Request $request
161 | *
162 | * @return WP_Error|WP_HTTP_Response|WP_REST_Response
163 | */
164 | public function track_popup_closed( WP_REST_Request $request ) {
165 |
166 | $id = absint( $request->get_param( 'popup_id' ) );
167 |
168 | $popup = new Holler_Popup( $id );
169 |
170 | if ( ! $popup->exists() ) {
171 | return self::ERROR_404();
172 | }
173 |
174 | if ( ! is_user_logged_in() ){
175 | return self::ERROR_401();
176 | }
177 |
178 | $closed_popups = wp_parse_id_list( get_user_meta( get_current_user_id(), 'hollerbox_closed_popups', true ) );
179 | $closed_popups[] = $popup->ID;
180 | update_user_meta( get_current_user_id(), 'hollerbox_closed_popups', implode( ',', array_unique( $closed_popups ) ) );
181 |
182 | return rest_ensure_response( [
183 | 'success' => true
184 | ] );
185 | }
186 |
187 | /**
188 | * Track a popup conversion
189 | *
190 | * @param WP_REST_Request $request
191 | *
192 | * @return WP_Error|WP_HTTP_Response|WP_REST_Response
193 | */
194 | public function track_conversion( WP_REST_Request $request ) {
195 |
196 | $id = absint( $request->get_param( 'popup_id' ) );
197 |
198 | $popup = new Holler_Popup( $id );
199 |
200 | if ( ! $popup->exists() ) {
201 | return self::ERROR_404();
202 | }
203 |
204 | // Parse the location
205 | $location = parse_url( sanitize_text_field( $request->get_param( 'location' ) ), PHP_URL_PATH );
206 | $content = sanitize_text_field( $request->get_param( 'content' ) );
207 |
208 | Holler_Reporting::instance()->add_conversion( $popup, $location, $content );
209 |
210 | if ( is_user_logged_in() ) {
211 | $conversions = wp_parse_id_list( get_user_meta( get_current_user_id(), 'hollerbox_popup_conversions', true ) );
212 | $conversions[] = $popup->ID;
213 | update_user_meta( get_current_user_id(), 'hollerbox_popup_conversions', implode( ',', array_unique( $conversions ) ) );
214 | }
215 |
216 | return rest_ensure_response( [
217 | 'success' => true
218 | ] );
219 | }
220 |
221 | /**
222 | * Track an impression
223 | *
224 | * @param WP_REST_Request $request
225 | *
226 | * @return WP_Error|WP_HTTP_Response|WP_REST_Response
227 | */
228 | public function track_impression( WP_REST_Request $request ) {
229 |
230 | $id = absint( $request->get_param( 'popup_id' ) );
231 |
232 | $popup = new Holler_Popup( $id );
233 |
234 | if ( ! $popup->exists() ) {
235 | return self::ERROR_404();
236 | }
237 |
238 | // Parse the location
239 | $location = parse_url( sanitize_text_field( $request->get_param( 'location' ) ), PHP_URL_PATH );
240 |
241 | Holler_Reporting::instance()->add_impression( $popup, $location );
242 |
243 | return rest_ensure_response( [
244 | 'success' => true
245 | ] );
246 | }
247 |
248 | /**
249 | * Standard 404 message
250 | *
251 | * @return WP_Error
252 | */
253 | public static function ERROR_404() {
254 | return new WP_Error( 'missing', 'Popup not found.', [ 'status' => 404 ] );
255 | }
256 |
257 | /**
258 | * Standard 401 message
259 | *
260 | * @return WP_Error
261 | */
262 | public static function ERROR_401() {
263 | return new WP_Error( 'access_denied', 'Insufficient permissions.', [ 'status' => 401 ] );
264 | }
265 |
266 | /**
267 | * Install either MailHawk or Groundhogg remotely
268 | *
269 | * @param WP_REST_Request $request
270 | *
271 | * @return bool|void|WP_Error
272 | */
273 | public function install_plugin( WP_REST_Request $request ) {
274 |
275 | $slug = sanitize_text_field( $request->get_param( 'slug' ) );
276 |
277 | if ( ! in_array( $slug, [ 'groundhogg', 'mailhawk' ] ) ) {
278 | return new WP_Error( 'invalid_slug', 'Not a valid slug.', [ 'status' => 401 ] );
279 | }
280 |
281 | $installed = $this->_install_plugin( $slug );
282 |
283 | if ( is_wp_error( $installed ) ) {
284 | return $installed;
285 | }
286 |
287 | if ( ! $installed ) {
288 | return new WP_Error( 'not_installed', 'Unable to install.', [ 'status' => 500 ] );
289 | }
290 |
291 | $response = [];
292 |
293 | switch ( $slug ) {
294 | case 'mailhawk':
295 |
296 | if ( ! defined( 'MAILHAWK_VERSION' ) ) {
297 | return new WP_Error( 'mailhawk_missing', 'Unable to find MailHawk.', [ 'status' => 500 ] );
298 | }
299 |
300 | $response = [
301 | 'partner_id' => '', // todo change this
302 | 'register_url' => esc_url( trailingslashit( MAILHAWK_LICENSE_SERVER_URL ) ),
303 | 'redirect_uri' => \MailHawk\get_admin_mailhawk_uri(),
304 | 'client_state' => esc_attr( \MailHawk\Keys::instance()->state() ),
305 | ];
306 |
307 | break;
308 | case 'groundhogg':
309 | $response = [];
310 | break;
311 | }
312 |
313 |
314 | return rest_ensure_response( wp_parse_args( $response, [
315 | 'success' => true
316 | ] ) );
317 |
318 | }
319 |
320 | /**
321 | * Pre-process the post content
322 | *
323 | * @param $slug string
324 | *
325 | * @return WP_Error|bool
326 | */
327 | public function _install_plugin( $slug ) {
328 |
329 | include_once ABSPATH . 'wp-admin/includes/plugin.php';
330 |
331 | foreach ( get_plugins() as $path => $details ) {
332 |
333 | if ( false === strpos( $path, sprintf( '/%s.php', $slug ) ) ) {
334 | continue;
335 | }
336 |
337 | $activate = activate_plugin( $path );
338 |
339 | if ( is_wp_error( $activate ) ) {
340 | return $activate;
341 | }
342 |
343 | return true;
344 | }
345 |
346 | include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
347 | include_once ABSPATH . 'wp-admin/includes/file.php';
348 | include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
349 |
350 | // Use the WordPress Plugins API to get the plugin download link.
351 | $api = plugins_api(
352 | 'plugin_information',
353 | array(
354 | 'slug' => $slug,
355 | )
356 | );
357 |
358 | if ( is_wp_error( $api ) ) {
359 | return $api;
360 | }
361 |
362 | // Use the AJAX upgrader skin to quietly install the plugin.
363 | $upgrader = new \Plugin_Upgrader( new \WP_Ajax_Upgrader_Skin() );
364 | $install = $upgrader->install( $api->download_link );
365 |
366 | if ( is_wp_error( $install ) ) {
367 | return $install;
368 | }
369 |
370 | $activate = activate_plugin( $upgrader->plugin_info() );
371 |
372 | if ( is_wp_error( $activate ) ) {
373 | return $activate;
374 | }
375 |
376 | return true;
377 | }
378 |
379 | /**
380 | * Submit a form for a specific popup
381 | *
382 | * @param WP_REST_Request $request
383 | *
384 | * @return WP_REST_Response|WP_Error
385 | */
386 | public function submit( WP_REST_Request $request ) {
387 |
388 | $id = absint( $request->get_param( 'popup_id' ) );
389 |
390 | $popup = new Holler_Popup( $id );
391 |
392 | if ( ! $popup->exists() ) {
393 | return self::ERROR_404();
394 | }
395 |
396 | $lead = new Holler_Lead( $request );
397 |
398 | $response = $popup->submit( $lead );
399 |
400 | if ( is_wp_error( $response ) ) {
401 | return rest_ensure_response( $response );
402 | }
403 |
404 | if ( $response['status'] === 'success' ) {
405 | $this->track_conversion( $request );
406 | }
407 |
408 | return rest_ensure_response( $response );
409 | }
410 |
411 | /**
412 | * Update a popup with some specific settings
413 | *
414 | * @param WP_REST_Request $request
415 | *
416 | * @return WP_REST_Response|WP_Error
417 | */
418 | public function read( WP_REST_Request $request ) {
419 |
420 | $id = absint( $request->get_param( 'popup_id' ) );
421 |
422 | $popup = new Holler_Popup( $id );
423 |
424 | if ( ! $popup->exists() ) {
425 | return self::ERROR_404();
426 | }
427 |
428 | return rest_ensure_response( $popup );
429 | }
430 |
431 | /**
432 | * Update a popup with some specific settings
433 | *
434 | * @param WP_REST_Request $request
435 | *
436 | * @return WP_REST_Response|WP_Error
437 | */
438 | public function update( WP_REST_Request $request ) {
439 |
440 | $id = absint( $request->get_param( 'popup_id' ) );
441 |
442 | $popup = new Holler_Popup( $id );
443 |
444 | if ( ! $popup->exists() ) {
445 | return self::ERROR_404();
446 | }
447 |
448 | $new_settings = $request->get_json_params();
449 |
450 | $result = $popup->update( $new_settings );
451 |
452 | if ( is_wp_error( $result ) ) {
453 | return $result;
454 | }
455 |
456 | return rest_ensure_response( $popup );
457 | }
458 |
459 | /**
460 | * Delete a popup
461 | *
462 | * @param WP_REST_Request $request
463 | *
464 | * @return WP_Error|WP_REST_Response
465 | */
466 | public function delete( WP_REST_Request $request ) {
467 | $id = absint( $request->get_param( 'popup_id' ) );
468 |
469 | $popup = new Holler_Popup( $id );
470 |
471 | if ( ! $popup->exists() ) {
472 | return self::ERROR_404();
473 | }
474 |
475 | $popup->delete();
476 |
477 | return rest_ensure_response( [ 'success' => true ] );
478 | }
479 |
480 | /**
481 | * Delete a popup
482 | *
483 | * @param WP_REST_Request $request
484 | *
485 | * @return WP_Error|WP_REST_Response
486 | */
487 | public function update_settings( WP_REST_Request $request ) {
488 | $settings = $request->get_param( 'settings' );
489 |
490 | foreach ( $settings as $option_name => $option_value ) {
491 | Holler_Settings::instance()->update( $option_name, $option_value, false );
492 | }
493 |
494 | Holler_Settings::instance()->commit();
495 |
496 | return rest_ensure_response( [ 'success' => true ] );
497 | }
498 |
499 | /**
500 | * Get options for the display condition pickers
501 | *
502 | * @param WP_REST_Request $request
503 | *
504 | * @return WP_Error|WP_HTTP_Response|WP_REST_Response
505 | */
506 | public function read_options( WP_REST_Request $request ) {
507 |
508 | $search = $request->get_param( 'search' );
509 | $options = [];
510 |
511 | if ( $post_type = $request->get_param( 'post_type' ) ) {
512 |
513 | $posts = get_posts( [
514 | 'numberposts' => 30,
515 | 'post_type' => $post_type,
516 | 's' => $search,
517 | ] );
518 |
519 | $options = array_map( function ( $post ) {
520 | return [ 'id' => $post->ID, 'text' => $post->post_title ];
521 | }, $posts );
522 | }
523 |
524 | if ( $taxonomy = $request->get_param( 'taxonomy' ) ) {
525 |
526 | $terms = get_terms( [
527 | 'taxonomy' => $taxonomy,
528 | 'hide_empty' => false,
529 | 'search' => $search,
530 | 'number' => 30
531 | ] );
532 |
533 | $options = array_map( function ( $term ) {
534 | return [ 'id' => $term->term_id, 'text' => $term->name ];
535 | }, $terms );
536 | }
537 |
538 | return rest_ensure_response( $options );
539 |
540 | }
541 |
542 | public function permission_callback() {
543 | return current_user_can( 'edit_popups' );
544 | }
545 |
546 | public function options_permission_callback() {
547 | return current_user_can( 'manage_options' );
548 | }
549 |
550 | public function plugins_permission_callback() {
551 | return current_user_can( 'install_plugins' );
552 | }
553 |
554 | }
555 |
--------------------------------------------------------------------------------
/includes/class-holler-frontend.php:
--------------------------------------------------------------------------------
1 | is_builder_preview() ):
37 | ?>
38 |
39 |
43 |
56 |
61 |
68 | get( 'script_debug_mode' ) ? '' : '.min';
76 |
77 | wp_enqueue_style( 'hollerbox-popups', Holler_Box_URL . 'assets/css/popups.css', [], HOLLERBOX_VERSION );
78 | wp_enqueue_script( 'hollerbox-popups', Holler_Box_URL . 'assets/js/popups' . $dot_min . '.js', [], HOLLERBOX_VERSION, true );
79 |
80 | $cookie_lifetime = strtotime( '+' . Holler_Settings::instance()->get( 'cookie_lifetime', 1 ) . ' ' . Holler_Settings::instance()->get( 'cookie_lifetime_period', 'months' ), 0 );
81 |
82 | $l10n = [
83 | 'cookie_lifetime' => $cookie_lifetime,
84 | 'active' => array_map( function ( $popup ) {
85 | $popup = $popup->jsonSerialize();
86 |
87 | // Remove secret properties
88 | unset( $popup['integrations'] );
89 |
90 | return $popup;
91 | }, $this->active ),
92 | 'home_url' => home_url(),
93 | 'nav' => [
94 | 'home' => home_url(),
95 | 'login' => wp_login_url(),
96 | 'lost_password' => wp_lostpassword_url(),
97 | 'register' => wp_registration_url(),
98 | 'privacy_page' => get_privacy_policy_url(),
99 | ],
100 | 'is_preview' => is_preview(),
101 | 'is_frontend' => ! is_admin(),
102 | 'is_builder_preview' => $this->is_builder_preview(),
103 | 'is_user_logged_in' => is_user_logged_in(),
104 | 'routes' => [
105 | 'root' => rest_url( 'hollerbox' ),
106 | 'conversion' => rest_url( 'hollerbox/conversion' ),
107 | 'impression' => rest_url( 'hollerbox/impression' ),
108 | 'submit' => rest_url( 'hollerbox/submit' ),
109 | 'closed' => rest_url( 'hollerbox/closed' ),
110 | ],
111 | 'nonces' => [
112 | '_wprest' => wp_create_nonce( 'wp_rest' )
113 | ],
114 | 'settings' => Holler_Settings::instance()->get( [
115 | 'credit_disabled',
116 | 'gdpr_enabled',
117 | 'gdpr_text',
118 | 'cookie_compliance',
119 | 'cookie_name',
120 | 'cookie_value',
121 | 'script_debug_mode',
122 | 'stacked_delay'
123 | ], [
124 | 'credit_disabled' => false,
125 | 'gdpr_enabled' => false,
126 | 'gdpr_text' => '',
127 | 'cookie_compliance' => false,
128 | 'cookie_name' => 'viewed_cookie_policy',
129 | 'cookie_value' => 'yes',
130 | 'stacked_delay' => 5,
131 | ] )
132 | ];
133 |
134 | if ( defined( 'GROUNDHOGG_VERSION' ) ){
135 | $l10n['is_current_contact'] = \Groundhogg\is_a_contact( \Groundhogg\get_current_contact() );
136 | }
137 |
138 | do_action( 'hollerbox/scripts', $this );
139 | do_action( 'hollerbox/frontend/scripts', $this );
140 |
141 | wp_add_inline_script( 'hollerbox-popups', "HollerBox = " . wp_json_encode( $l10n ), 'before' );
142 |
143 | }
144 |
145 | /**
146 | * Add popup classes to the main body
147 | *
148 | * @param $classes
149 | *
150 | * @return array|mixed
151 | */
152 | public function body_classes( $classes ) {
153 |
154 | foreach ( $this->active as $popup ) {
155 | $classes = array_merge( $classes, $popup->get_body_classes() );
156 | }
157 |
158 | return $classes;
159 | }
160 |
161 | /**
162 | * @param $popup Holler_Popup
163 | */
164 | protected function add_active( $popup ) {
165 | $this->active[] = $popup;
166 | }
167 |
168 | /**
169 | * There are active popups on this page
170 | *
171 | * @return bool
172 | */
173 | public function has_active() {
174 | return ! empty( $this->active );
175 | }
176 |
177 | /**
178 | * Find which popups are active for the current request
179 | *
180 | * @param $query
181 | */
182 | public function get_active_popups() {
183 |
184 | // Do not run in admin
185 | if ( is_admin() ) {
186 | return;
187 | }
188 |
189 | if ( $this->is_builder_preview() ) {
190 |
191 | // hide admin bar
192 | add_filter( 'show_admin_bar', '__return_false' );
193 |
194 | // prevent query monitor output in preview
195 | add_filter( 'qm/process', '__return_false' );
196 |
197 | // Suppress popups from being displayed
198 | return;
199 | }
200 |
201 | $args = [ 'post_type' => 'hollerbox', 'posts_per_page' => - 1, 'post_status' => 'publish' ];
202 |
203 | // The Query
204 | $the_query = new WP_Query( $args );
205 | $popups = [];
206 |
207 | // The Loop
208 | if ( $the_query->have_posts() ) {
209 |
210 | while ( $the_query->have_posts() ) {
211 | $the_query->the_post();
212 | $id = get_the_id();
213 |
214 | $popup = new Holler_Popup( $id );
215 |
216 | $popups[] = $popup;
217 | }
218 |
219 | /* Restore original Post Data */
220 | wp_reset_postdata();
221 | }
222 |
223 | // only show active popups for the current query
224 | foreach ( $popups as $popup ) {
225 | if ( $popup->can_show() ) {
226 | $this->add_active( $popup );
227 | }
228 | }
229 |
230 | if ( $this->has_active() && ! $this->is_builder_preview() ) {
231 | add_action( 'admin_bar_menu', [ $this, 'holler_box_menu_item' ], 99 );
232 | }
233 |
234 | }
235 |
236 | public static function HollerIcon( $props = [] ) {
237 |
238 | $props = wp_parse_args( $props, [
239 | 'width' => '20px',
240 | 'height' => '20px',
241 | ] );
242 |
243 | return '
244 |
245 |
246 |
247 |
249 | ';
250 | }
251 |
252 | /**
253 | * Add HollerBox menu item to admin bar
254 | *
255 | * @param $wp_admin_bar WP_Admin_Bar
256 | *
257 | * @return void
258 | */
259 | public function holler_box_menu_item( $wp_admin_bar ) {
260 |
261 | if ( ! $this->has_active() ) {
262 | return;
263 | }
264 |
265 | $wp_admin_bar->add_node( [
266 | 'id' => 'manage-hollerbox',
267 | 'title' => self::HollerIcon( [
268 | 'style' => [
269 | 'padding-top' => '5px'
270 | ]
271 | ] )
272 | ] );
273 |
274 | foreach ( $this->active as $popup ) {
275 |
276 | $wp_admin_bar->add_node( [
277 | 'parent' => 'manage-hollerbox',
278 | 'id' => 'holler-' . $popup->ID,
279 | 'title' => $popup->post_title,
280 | 'href' => get_edit_post_link( $popup->ID )
281 | ] );
282 |
283 | }
284 |
285 | }
286 |
287 | /**
288 | * Convert array to HTML tag attributes
289 | *
290 | * @param $atts
291 | *
292 | * @return string
293 | */
294 | static function array_to_atts( $atts ) {
295 | $tag = '';
296 |
297 | if ( ! is_array( $atts ) ) {
298 | return '';
299 | }
300 |
301 | foreach ( $atts as $key => $value ) {
302 |
303 | if ( empty( $value ) ) {
304 | continue;
305 | }
306 |
307 | $key = strtolower( $key );
308 |
309 | switch ( $key ) {
310 | case 'style':
311 | $value = self::array_to_css( $value );
312 | break;
313 | case 'href':
314 | case 'action':
315 | case 'src':
316 | $value = strpos( $value, 'data:image/png;base64,' ) === false ? esc_url( $value ) : $value;
317 | break;
318 | default:
319 | if ( is_array( $value ) ) {
320 | $value = implode( ' ', $value );
321 | }
322 |
323 | $value = esc_attr( $value );
324 | break;
325 |
326 | }
327 |
328 | $tag .= sanitize_key( $key ) . '="' . $value . '" ';
329 | }
330 |
331 | return $tag;
332 | }
333 |
334 | /**
335 | * Convert array to CSS style attributes
336 | *
337 | * @param $atts
338 | *
339 | * @return string
340 | */
341 | static function array_to_css( $atts ) {
342 |
343 | if ( ! is_array( $atts ) ) {
344 | return $atts;
345 | }
346 |
347 | $css = '';
348 | foreach ( $atts as $key => $value ) {
349 |
350 | if ( is_array( $value ) ) {
351 | $value = implode( ' ', $value );
352 | }
353 |
354 | $css .= sanitize_key( $key ) . ':' . esc_attr( $value ) . ';';
355 | }
356 |
357 | return $css;
358 | }
359 |
360 |
361 | }
362 |
--------------------------------------------------------------------------------
/includes/class-holler-integrations.php:
--------------------------------------------------------------------------------
1 | init();
18 | }
19 | }
20 |
21 | /**
22 | * Registry of callbacks for specific integrations
23 | *
24 | * @var callable[]
25 | */
26 | private static $integrations = [];
27 |
28 | /**
29 | * Register an integration handler
30 | *
31 | * @param $id string
32 | * @param $callback callable
33 | */
34 | public static function register( $id, $callback ) {
35 |
36 | if ( ! is_callable( $callback ) ) {
37 | return;
38 | }
39 |
40 | self::$integrations[ $id ] = $callback;
41 | }
42 |
43 | /**
44 | * Do an integration
45 | *
46 | * @param $integration array
47 | * @param $lead Holler_Lead
48 | * @param $popup Holler_Popup
49 | *
50 | * @return true|WP_Error false if the provided integration is not registered
51 | */
52 | public static function _do( $integration, $lead, $popup ) {
53 |
54 | // Setup the instance and init integrations
55 | if ( empty( self::$integrations ) ) {
56 | self::instance();
57 | }
58 |
59 | $type = $integration['type'];
60 |
61 | if ( ! isset( self::$integrations[ $type ] ) ) {
62 | return new WP_Error( 'unknown_integration', 'Unknown integration type ' . $type );
63 | }
64 |
65 | /**
66 | * Action before the integration
67 | *
68 | * @param $lead Holler_Lead
69 | * @param $popup Holler_Popup
70 | */
71 | do_action( "hollerbox/integrations/$type/before", $lead, $popup );
72 |
73 | // Do the integration
74 | $result = call_user_func( self::$integrations[ $type ], $integration, $lead, $popup );
75 |
76 | /**
77 | * Action after the integration
78 | *
79 | * @param $lead Holler_Lead
80 | * @param $popup Holler_Popup
81 | */
82 | do_action( "hollerbox/integrations/$type/after", $lead, $popup );
83 |
84 | return $result;
85 | }
86 |
87 | /**
88 | * Register the basic integration types
89 | */
90 | public function init() {
91 |
92 | self::register( 'email', [ $this, 'email' ] );
93 | self::register( 'groundhogg', [ $this, 'groundhogg' ] );
94 | self::register( 'webhook', [ $this, 'webhook' ] );
95 | self::register( 'zapier', [ $this, 'zapier' ] );
96 |
97 | do_action( 'hollerbox/register_integrations' );
98 | }
99 |
100 | /**
101 | * @var WP_Error
102 | */
103 | protected $wp_mail_error;
104 |
105 | /**
106 | * Catch email failed error
107 | *
108 | * @param $wp_error
109 | *
110 | * @return void
111 | */
112 | public function catch_mail_failed( $wp_error ) {
113 | $this->wp_mail_error = $wp_error;
114 | }
115 |
116 | /**
117 | * Process the email integration
118 | *
119 | * @param $props array
120 | * @param $lead Holler_Lead
121 | *
122 | * @return bool|mixed|void
123 | */
124 | public function email( $props, $lead ) {
125 |
126 | $props = wp_parse_args( $props, [
127 | 'to' => [],
128 | 'from' => '',
129 | 'reply_to' => '',
130 | 'subject' => '',
131 | 'content' => '',
132 | ] );
133 |
134 | $to = array_map( function ( $email ) use ( $lead ) {
135 | return $email === '{{email}}' ? $lead->get_email() : $email;
136 | }, $props['to'] );
137 |
138 | $to = array_filter( $to, function ( $email ) {
139 | return is_email( $email );
140 | } );
141 |
142 | $replacements = [
143 | '{{email}}' => $lead->email,
144 | '{{name}}' => $lead->name,
145 | '{{full_name}}' => $lead->name,
146 | '{{first_name}}' => $lead->first_name,
147 | '{{last_name}}' => $lead->last_name,
148 | '{{phone}}' => $lead->phone,
149 | '{{location}}' => $lead->location,
150 | '{{referrer}}' => $lead->referrer,
151 | '{{ip_address}}' => $lead->get_ip(),
152 | '{{message}}' => $lead->get_message_formatted(),
153 | ];
154 |
155 | /**
156 | * Add additional replacements
157 | *
158 | * @param $replacements array
159 | * @param $props array
160 | * @param $lead Holler_Lead
161 | */
162 | $replacements = apply_filters( 'hollerbox/integrations/email/replacements', $replacements, $props, $lead );
163 |
164 | $message = wp_kses_post( $props['content'] );
165 | $message = str_replace( array_keys( $replacements ), array_values( $replacements ), $message );
166 |
167 | $subject = sanitize_text_field( $props['subject'] );
168 | $subject = str_replace( array_keys( $replacements ), array_values( $replacements ), $subject );
169 |
170 | $headers = [
171 | 'Content-Type: text/html',
172 | ];
173 |
174 | $reply_to = str_replace( '{{email}}', $lead->email, $props['reply_to'] );
175 |
176 | if ( is_email( $reply_to ) ) {
177 | $headers[] = sprintf( 'Reply-to: %s', $reply_to );
178 | }
179 |
180 | if ( is_email( $props['from'] ) ) {
181 | $headers[] = sprintf( 'From: %s', $props['from'] );
182 | }
183 |
184 | add_action( 'wp_mail_failed', [ $this, 'catch_mail_failed' ] );
185 |
186 | $result = wp_mail(
187 | $to,
188 | $subject,
189 | $message,
190 | $headers
191 | );
192 |
193 | remove_action( 'wp_mail_failed', [ $this, 'catch_mail_failed' ] );
194 |
195 | return $result ?: $this->wp_mail_error;
196 | }
197 |
198 | /**
199 | * Process the webhook integration
200 | *
201 | * @param $props array
202 | * @param $lead Holler_Lead
203 | * @param $popup Holler_Popup
204 | *
205 | * @return bool|mixed|void
206 | */
207 | public function webhook( $props, $lead, $popup ) {
208 |
209 | $props = wp_parse_args( $props, [
210 | 'url' => '',
211 | 'method' => 'post',
212 | 'payload' => 'json',
213 | ] );
214 |
215 | $headers = [];
216 |
217 | $body = [
218 | 'full_name' => $lead->get_name(),
219 | 'first_name' => $lead->get_first_name(),
220 | 'last_name' => $lead->get_last_name(),
221 | 'phone' => $lead->get_phone(),
222 | 'email' => $lead->get_email(),
223 | 'ip4' => $lead->get_ip(),
224 | 'gdpr_consent' => $lead->gdpr_consent,
225 | ];
226 |
227 | if ( $lead->message ) {
228 | $body['message'] = $lead->message;
229 | }
230 |
231 | /**
232 | * Filter the outgoing webhook body
233 | *
234 | * @param $body array
235 | * @param $props array
236 | * @param $lead Holler_Lead
237 | * @param $popup Holler_Popup
238 | */
239 | $body = apply_filters( 'hollerbox/integrations/webhook/body', $body, $props, $lead, $popup );
240 |
241 | if ( $props['method'] === 'get' ) {
242 | return wp_remote_get( add_query_arg( $body, $props['url'] ), [
243 | 'sslverify' => is_ssl(),
244 | 'user-agent' => 'HollerBox/' . HOLLERBOX_VERSION . '; ' . home_url()
245 | ] );
246 | }
247 |
248 | if ( $props['payload'] === 'json' ) {
249 | $body = wp_json_encode( $body );
250 | $headers['Content-type'] = sprintf( 'application/json; charset=%s', get_bloginfo( 'charset' ) );
251 | }
252 |
253 | $response = wp_remote_request( $props['url'], [
254 | 'method' => strtoupper( $props['method'] ),
255 | 'body' => $body,
256 | 'headers' => $headers,
257 | 'data_format' => 'body',
258 | 'sslverify' => is_ssl(),
259 | 'user-agent' => 'HollerBox/' . HOLLERBOX_VERSION . '; ' . home_url()
260 | ] );
261 |
262 | if ( is_wp_error( $response ) ) {
263 | return $response;
264 | }
265 |
266 | return true;
267 | }
268 |
269 | /**
270 | * Process the Zapier integration
271 | *
272 | * @param $props array
273 | * @param $lead Holler_Lead
274 | * @param $popup Holler_Popup
275 | *
276 | * @return bool|mixed|void
277 | */
278 | public function zapier( $props, $lead, $popup ) {
279 |
280 | $props = wp_parse_args( $props, [
281 | 'url' => '',
282 | ] );
283 |
284 | $props['method'] = 'POST';
285 | $props['payload'] = 'json';
286 |
287 | return $this->webhook( $props, $lead, $popup );
288 | }
289 |
290 | /**
291 | * Process the groundhogg integration
292 | *
293 | * @param $props array
294 | * @param $lead Holler_Lead
295 | *
296 | * @return bool|mixed|void
297 | */
298 | public function groundhogg( $props, $lead ) {
299 |
300 | if ( ! defined( 'GROUNDHOGG_VERSION' ) ) {
301 | return false;
302 | }
303 |
304 | $contact = new \Groundhogg\Contact( $lead->email );
305 |
306 | if ( ! $contact->exists() ) {
307 | $contact->create( [
308 | 'first_name' => $lead->first_name,
309 | 'last_name' => $lead->last_name,
310 | 'email' => $lead->email,
311 | ] );
312 | } else {
313 | $contact->update( array_filter( [
314 | 'first_name' => $lead->first_name,
315 | 'last_name' => $lead->last_name,
316 | ] ) );
317 | }
318 |
319 | $contact->add_tag( map_deep( $props['tags'], 'sanitize_text_field' ) );
320 |
321 | // Gave consent
322 | if ( $lead->gdpr_consent ) {
323 | $contact->set_marketing_consent();
324 | $contact->set_gdpr_consent();
325 | $contact->set_terms_agreement();
326 | }
327 |
328 | if ( $lead->message ) {
329 | $contact->update_meta( 'hollerbox_chat_message', $lead->message );
330 | }
331 |
332 | if ( $lead->phone ) {
333 | $contact->update_meta( 'primary_phone', $lead->phone );
334 | }
335 |
336 | \Groundhogg\after_form_submit_handler( $contact );
337 |
338 | $contact->update_meta( 'source_page', $lead->location );
339 |
340 | return true;
341 | }
342 |
343 | /**
344 | * Create a new user integration
345 | *
346 | * @param $props
347 | * @param $lead
348 | *
349 | * @return bool
350 | */
351 | public function user( $props, $lead ) {
352 |
353 | $props = wp_parse_args( $props, [
354 | 'role' => 'subscriber',
355 | 'format' => 'email',
356 | 'login' => false
357 | ] );
358 |
359 | $email_address = $lead->get_email();
360 |
361 | $password = wp_generate_password();
362 |
363 | $role = $props['role'];
364 |
365 | // Email already exists...
366 | if ( email_exists( $email_address ) ) {
367 | return false;
368 | }
369 |
370 | switch ( $props['format'] ) {
371 | default:
372 | case 'email_address':
373 | $username = $lead->get_email();
374 | break;
375 | case 'first_last':
376 | $username = strtolower( sprintf( "%s_%s", $lead->get_first_name(), $lead->get_last_name() ) );
377 | break;
378 | case 'last_first':
379 | $username = strtolower( sprintf( "%s_%s", $lead->get_last_name(), $lead->get_first_name() ) );
380 | break;
381 | }
382 |
383 | // More or less guaranteed unique at this point.
384 | $username = $this->generate_unique_username( $username );
385 |
386 | $user_id = wp_create_user( $username, $password, $email_address );
387 | $user = new \WP_User( $user_id );
388 | $user->set_role( $role );
389 |
390 | $user->first_name = $lead->get_first_name();
391 | $user->last_name = $lead->get_last_name();
392 |
393 | wp_update_user( $user );
394 |
395 | wp_new_user_notification( $user_id, null, 'user' );
396 |
397 | return true;
398 |
399 | }
400 |
401 | /**
402 | * Ensure a username is unique by checking if it is already taken, and if it is adding a unique string after it.
403 | *
404 | * @param string $username
405 | * @param bool $known_exists to avoid double-checking the same username during every recursion
406 | *
407 | * @return string
408 | */
409 | private function generate_unique_username( $username, $known_exists = false ) {
410 |
411 | $username = sanitize_user( $username );
412 |
413 | if ( ! $known_exists && ! username_exists( $username ) ) {
414 | return $username;
415 | }
416 |
417 | $new_username = uniqid( $username . '_' );
418 |
419 | if ( ! username_exists( $new_username ) ) {
420 | return $new_username;
421 | } else {
422 | return $this->generate_unique_username( $username, true );
423 | }
424 | }
425 |
426 | }
427 |
428 |
--------------------------------------------------------------------------------
/includes/class-holler-lead.php:
--------------------------------------------------------------------------------
1 | name = sanitize_text_field( $request->get_param( 'name' ) );
26 |
27 | $parts = explode( ' ', $this->name );
28 | $this->first_name = trim( $parts[0] );
29 |
30 | if ( isset( $parts[1] ) ) {
31 | $this->last_name = trim( $parts[1] );
32 | }
33 |
34 | $this->email = sanitize_email( strtolower( $request->get_param( 'email' ) ) );
35 |
36 | if ( is_user_logged_in() ) {
37 |
38 | $user = wp_get_current_user();
39 |
40 | if ( ! $this->email ) {
41 | $this->email = $user->user_email;
42 | }
43 |
44 | if ( ! $this->first_name ) {
45 | $this->first_name = $user->first_name;
46 | }
47 |
48 | if ( ! $this->last_name ) {
49 | $this->last_name = $user->last_name;
50 | }
51 | }
52 |
53 | if ( defined( 'GROUNDHOGG_VERSION' ) && \Groundhogg\is_a_contact( \Groundhogg\get_current_contact() ) ) {
54 |
55 | $contact = \Groundhogg\get_current_contact();
56 |
57 | if ( ! $this->email ) {
58 | $this->email = $contact->get_email();
59 | }
60 |
61 | if ( ! $this->first_name ) {
62 | $this->first_name = $contact->get_first_name();
63 | }
64 |
65 | if ( ! $this->last_name ) {
66 | $this->last_name = $contact->get_last_name();
67 | }
68 | }
69 |
70 | $this->phone = sanitize_text_field( $request->get_param( 'phone' ) );
71 | $this->location = sanitize_text_field( $request->get_param( 'location' ) );
72 | $this->referrer = sanitize_text_field( $request->get_param( 'referer' ) );
73 | $this->gdpr_consent = $request->get_param( 'gdpr_consent' ) === 'yes';
74 | $this->message = sanitize_textarea_field( $request->get_param( 'message' ) );
75 | $this->request = $request;
76 |
77 | /**
78 | * When a lead is initialized
79 | *
80 | * @param $lead Holler_Lead
81 | * @param $request WP_REST_Request
82 | */
83 | do_action( 'hollerbox/lead_init', $this, $request );
84 | }
85 |
86 | /**
87 | * Get the lead's email address
88 | *
89 | * @return string
90 | */
91 | public function get_email() {
92 | return $this->email;
93 | }
94 |
95 | /**
96 | * Get the lead's name
97 | *
98 | * @return string
99 | */
100 | public function get_name() {
101 | return $this->name;
102 | }
103 |
104 | /**
105 | * Get the first name
106 | *
107 | * @return string
108 | */
109 | public function get_first_name() {
110 | return $this->first_name;
111 | }
112 |
113 | /**
114 | * Get the last name
115 | *
116 | * @return string
117 | */
118 | public function get_last_name() {
119 | return $this->last_name;
120 | }
121 |
122 | /**
123 | * Get the phone number
124 | *
125 | * @return string
126 | */
127 | public function get_phone() {
128 | return $this->phone;
129 | }
130 |
131 | /**
132 | * Get the chat message
133 | *
134 | * @return string
135 | */
136 | public function get_message_formatted() {
137 | return wpautop( $this->message );
138 | }
139 |
140 | /**
141 | * Get the leads IP address
142 | *
143 | * @return string
144 | */
145 | public function get_ip() {
146 | if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) //check ip from share internet
147 | {
148 | $ip = $_SERVER['HTTP_CLIENT_IP'];
149 | } else if ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) //to check ip is pass from proxy
150 | {
151 | $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
152 | } else {
153 | $ip = $_SERVER['REMOTE_ADDR'];
154 | }
155 |
156 | return $ip;
157 | }
158 |
159 | #[ReturnTypeWillChange]
160 | public function offsetExists( $offset ) {
161 | return isset( $this->$offset ) || isset( $this->data[ $offset ] );
162 | }
163 |
164 | #[ReturnTypeWillChange]
165 | public function offsetGet( $offset ) {
166 | if ( property_exists( $this, $offset ) ) {
167 | return $this->$offset;
168 | }
169 |
170 | return $this->data[ $offset ];
171 | }
172 |
173 | #[ReturnTypeWillChange]
174 | public function offsetSet( $offset, $value ) {
175 | if ( property_exists( $this, $offset ) ) {
176 | $this->$offset = $value;
177 | }
178 |
179 | $this->data[ $offset ] = $value;
180 | }
181 |
182 | #[ReturnTypeWillChange]
183 | public function offsetUnset( $offset ) {
184 | if ( property_exists( $this, $offset ) ) {
185 | return;
186 | }
187 |
188 | unset( $this->data[ $offset ] );
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/includes/class-holler-licensing.php:
--------------------------------------------------------------------------------
1 | WP_REST_Server::CREATABLE,
28 | 'callback' => [ $this, 'activate' ],
29 | 'permission_callback' => [ $this, 'permission_callback' ]
30 | ],
31 | [
32 | 'methods' => WP_REST_Server::DELETABLE,
33 | 'callback' => [ $this, 'deactivate' ],
34 | 'permission_callback' => [ $this, 'permission_callback' ]
35 | ],
36 | ] );
37 |
38 | }
39 |
40 | /**
41 | * @since 0.1.0
42 | * @var Holler_Licensing $instance
43 | */
44 | private static $instance;
45 |
46 | /**
47 | * Get active instance
48 | *
49 | * @access public
50 | * @since 0.1.0
51 | * @return self The one true Holler_Box
52 | */
53 | public static function instance() {
54 | if ( ! self::$instance ) {
55 | self::$instance = new Holler_Licensing();
56 | }
57 |
58 | return self::$instance;
59 | }
60 |
61 | /**
62 | * Create an EDD updater for the pro version
63 | *
64 | * @param $file
65 | * @param $version
66 | *
67 | * @return Holler_EDD_SL_Plugin_Updater
68 | */
69 | public function edd_updater( $file, $version ){
70 |
71 | // EDD Stuff
72 | return new \Holler_EDD_SL_Plugin_Updater( self::STORE_URL, $file, [
73 | 'version' => $version,
74 | 'license' => Holler_Settings::instance()->get( 'license' ),
75 | 'item_id' => $this->get_pro_item_id(),
76 | 'url' => home_url(),
77 | 'author' => 'Groundhogg Inc.'
78 | ] );
79 | }
80 |
81 | /**
82 | * Get the ID of the item to license in the store
83 | *
84 | * @return mixed|void
85 | */
86 | public function get_pro_item_id(){
87 | return apply_filters( 'hollerbox/pro_item_id', self::PRO_ITEM_ID );
88 | }
89 |
90 | /**
91 | * Get the error message for a given error.
92 | *
93 | * @param $error
94 | * @param false $expiry
95 | *
96 | * @return string
97 | */
98 | protected function get_license_error_message( $error, $expiry = false ) {
99 |
100 | switch ( $error ) {
101 | case 'expired' :
102 | $message = sprintf(
103 | _x( 'Your license key expired on %s.', 'notice', 'groundhogg' ),
104 | date_i18n( get_option( 'date_format' ), strtotime( $expiry, current_time( 'timestamp' ) ) )
105 | );
106 | break;
107 | case 'invalid' :
108 | case 'disabled' :
109 | $message = _x( 'Your license key has been disabled.', 'notice', 'groundhogg' );
110 | break;
111 | case 'site_inactive' :
112 | $message = _x( 'Your license is not active for this URL.', 'notice', 'groundhogg' );
113 | break;
114 | case 'key_mismatch' :
115 | case 'invalid_item_id' :
116 | case 'item_name_mismatch' :
117 | $message = sprintf( _x( 'The extension you are licensing is unrecognized.', 'notice', 'groundhogg' ) );
118 | break;
119 | case 'missing_url' :
120 | case 'missing' :
121 | $message = sprintf( _x( 'This appears to be an invalid license key.', 'notice', 'groundhogg' ) );
122 | break;
123 | case 'no_activations_left':
124 | $message = _x( 'Your license key has reached its activation limit.', 'notice', 'groundhogg' );
125 | break;
126 | default :
127 | $message = _x( 'An error occurred, please try again.', 'notice', 'groundhogg' );
128 | break;
129 | }
130 |
131 | return $message;
132 | }
133 |
134 | /**
135 | * Activate a new license key
136 | *
137 | * @return array|bool|WP_Error
138 | */
139 | protected function _activate( $license ) {
140 |
141 | $existing_license = Holler_Settings::instance()->get( 'license' );
142 |
143 | // Exiting license is the same as is being added, return true
144 | if ( $existing_license && $license === $existing_license ) {
145 | return true;
146 | }
147 |
148 | // A new license is being activated, let's deactivate the old one
149 | if ( $existing_license ) {
150 | $res = $this->_deactivate();
151 |
152 | if ( is_wp_error( $res ) ) {
153 | return $res;
154 | }
155 | }
156 |
157 | $response = wp_remote_post( self::STORE_URL, [
158 | 'body' => [
159 | 'edd_action' => 'activate_license',
160 | 'item_id' => $this->get_pro_item_id(),
161 | 'license' => $license,
162 | 'url' => home_url(),
163 | ]
164 | ] );
165 |
166 | if ( is_wp_error( $response ) ) {
167 | return $response;
168 | }
169 |
170 | $license_data = json_decode( wp_remote_retrieve_body( $response ) );
171 |
172 | if ( false === $license_data->success ) {
173 | $message = self::get_license_error_message( $license_data->error, $license_data->expires );
174 |
175 | return new WP_Error( $license_data->error, $message );
176 | }
177 |
178 | $expiry = $license_data->expires;
179 |
180 | Holler_Settings::instance()->update( 'license', $license );
181 | Holler_Settings::instance()->update( 'license_expiry', $expiry );
182 | Holler_Settings::instance()->update( 'is_licensed', true );
183 |
184 | return true;
185 | }
186 |
187 | /**
188 | * Deactivate the current license key
189 | *
190 | * @return array|bool|WP_Error
191 | */
192 | protected function _deactivate() {
193 |
194 | $existing_license = Holler_Settings::instance()->get( 'license' );
195 |
196 | if ( ! $existing_license ) {
197 | return true;
198 | }
199 |
200 | $response = wp_remote_post( self::STORE_URL, [
201 | 'body' => [
202 | 'edd_action' => 'deactivate_license',
203 | 'item_id' => $this->get_pro_item_id(),
204 | 'license' => $existing_license,
205 | 'url' => home_url(),
206 | ]
207 | ] );
208 |
209 | if ( is_wp_error( $response ) ) {
210 | return $response;
211 | }
212 |
213 | Holler_Settings::instance()->update( 'is_licensed', false );
214 | Holler_Settings::instance()->update( 'license', '' );
215 | Holler_Settings::instance()->update( 'license_expiry', '' );
216 |
217 | return true;
218 | }
219 |
220 | /**
221 | * Activate a license for the first time
222 | *
223 | * @param WP_REST_Request $request
224 | *
225 | * @return WP_REST_Response|WP_Error
226 | */
227 | public function activate( WP_REST_Request $request ) {
228 |
229 | $license = sanitize_text_field( $request->get_param( 'license' ) );
230 |
231 | $result = $this->_activate( $license );
232 |
233 | if ( is_wp_error( $result ) ) {
234 | return $result;
235 | }
236 |
237 | return rest_ensure_response( [
238 | 'success' => true,
239 | 'license_data' => [
240 | 'is_licensed' => true,
241 | 'license' => Holler_Settings::instance()->get( 'license' ),
242 | 'license_expiry' => Holler_Settings::instance()->get( 'license_expiry' ),
243 | ]
244 | ] );
245 | }
246 |
247 | /**
248 | * Deactivate the current license
249 | *
250 | * @param WP_REST_Request $request
251 | *
252 | * @return array|bool|WP_Error|WP_HTTP_Response|WP_REST_Response
253 | */
254 | public function deactivate( WP_REST_Request $request ) {
255 |
256 | $result = $this->_deactivate();
257 |
258 | if ( is_wp_error( $result ) ) {
259 | return $result;
260 | }
261 |
262 | return rest_ensure_response( [
263 | 'success' => true,
264 | ] );
265 | }
266 |
267 |
268 | public function permission_callback() {
269 | return current_user_can( 'manage_options' );
270 | }
271 |
272 | }
273 |
--------------------------------------------------------------------------------
/includes/class-holler-reporting.php:
--------------------------------------------------------------------------------
1 | table_name = $wpdb->prefix . 'hollerbox_stats';
35 |
36 | add_action( 'deleted_post', [ $this, 'maybe_delete_stats' ], 10, 2 );
37 | }
38 |
39 | /**
40 | * Delete associated stats from the reporting because we no longer need them
41 | *
42 | * @param $post_id
43 | * @param $post WP_Post
44 | *
45 | * @return void
46 | */
47 | public function maybe_delete_stats( $post_id, $post ) {
48 |
49 | if ( $post->post_type !== 'hollerbox' ) {
50 | return;
51 | }
52 |
53 | global $wpdb;
54 |
55 | $wpdb->query( "DELETE FROM $this->table_name WHERE popup_id = $post_id" );
56 | }
57 |
58 | /**
59 | * Create or upgrade the table depending on the table version
60 | *
61 | * @return void
62 | */
63 | public function maybe_create_table() {
64 | $this->create_table();
65 | }
66 |
67 | /**
68 | * Check if the stats table exists
69 | *
70 | * @since 2.4
71 | *
72 | * @param string $table The table name
73 | *
74 | * @return bool If the table name exists
75 | */
76 | public function table_exists() {
77 | global $wpdb;
78 |
79 | return $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE '%s'", $this->table_name ) ) === $this->table_name;
80 | }
81 |
82 | /**
83 | * Drops the table
84 | */
85 | public function drop() {
86 |
87 | if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
88 | exit;
89 | }
90 |
91 | delete_option( $this->table_name . '_table_version' );
92 |
93 | global $wpdb;
94 |
95 | $wpdb->query( "DROP TABLE IF EXISTS " . $this->table_name );
96 | }
97 |
98 | /**
99 | * Creates the table
100 | *
101 | * @return void
102 | */
103 | public function create_table() {
104 |
105 | global $wpdb;
106 |
107 | require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
108 |
109 | $charset_collate = $wpdb->get_charset_collate();
110 |
111 | $max_index_length = $this->max_key_length();
112 |
113 | $sql = "CREATE TABLE " . $this->table_name . " (
114 | s_type varchar(10) NOT NULL,
115 | s_date date NOT NULL,
116 | s_count INT unsigned NOT NULL,
117 | popup_id bigint(20) unsigned NOT NULL,
118 | location varchar($max_index_length) NOT NULL,
119 | content varchar($max_index_length) NOT NULL,
120 | PRIMARY KEY (popup_id, s_type, s_date, location, content),
121 | KEY s_date (s_date),
122 | KEY s_type (s_type),
123 | KEY popup_id (popup_id),
124 | KEY content (content)
125 | ) $charset_collate ENGINE=InnoDB;";
126 |
127 | dbDelta( $sql );
128 |
129 | update_option( $this->table_name . '_table_version', self::TABLE_VERSION );
130 | }
131 |
132 | /**
133 | * @throws Exception
134 | *
135 | * @param Holler_Popup $popup
136 | * @param string $location
137 | * @param string $content
138 | *
139 | * @param string $type
140 | *
141 | * @return void
142 | */
143 | protected function increment_stat( string $type, Holler_Popup $popup, $location, $content = '' ) {
144 | global $wpdb;
145 |
146 | $date = new DateTime( 'now', wp_timezone() );
147 |
148 | $wpdb->query( $wpdb->prepare(
149 | "INSERT INTO $this->table_name (s_type, s_count, popup_id, location, content, s_date)
150 | VALUES (%s, %d, %d, %s, %s, %s)
151 | ON DUPLICATE KEY UPDATE s_count = s_count + 1",
152 | $type, 1, $popup->ID, $location, $content, $date->format( 'Y-m-d' ) ) );
153 | }
154 |
155 | /**
156 | * Increment the daily impression count for the given popup
157 | *
158 | * @param $popup Holler_Popup
159 | * @param $location string
160 | *
161 | * @return void
162 | */
163 | public function add_impression( Holler_Popup $popup, string $location ) {
164 | $this->increment_stat( 'impression', $popup, $location );
165 | }
166 |
167 | /**
168 | * Increment the daily conversion count for the given popup
169 | *
170 | * @param $popup Holler_Popup
171 | * @param $location string
172 | * @param $content string
173 | *
174 | * @return void
175 | */
176 | public function add_conversion( Holler_Popup $popup, string $location, string $content ) {
177 | $this->increment_stat( 'conversion', $popup, $location, $content );
178 | }
179 |
180 | /**
181 | * Get the impression count for a given interval
182 | *
183 | * @param $type string
184 | * @param $popup Holler_Popup
185 | * @param $interval DateInterval
186 | *
187 | * @return int
188 | */
189 | public function get_total_popup_count_for_interval( string $type, Holler_Popup $popup, DateInterval $interval ) {
190 |
191 | $date = new DateTime( 'now', wp_timezone() );
192 | $today = $date->format( 'Y-m-d' );
193 | $date->sub( $interval );
194 | $prev = $date->format( 'Y-m-d' );
195 |
196 | return $this->_get_total_count_for_interval( [
197 | 'popup_id' => $popup->ID,
198 | 'after' => $prev,
199 | 'before' => $today,
200 | 's_type' => $type
201 | ] );
202 | }
203 |
204 | /**
205 | * Get the impression count for a given interval
206 | *
207 | * @param $query
208 | *
209 | * @return int
210 | */
211 | public function _get_total_count_for_interval( $query = [] ) {
212 |
213 | global $wpdb;
214 |
215 | $cache_key = md5( wp_json_encode( $query ) );
216 |
217 | $count = wp_cache_get( $cache_key, 'hollerbox:counts', null, $found );
218 |
219 | if ( $found ) {
220 | return $count;
221 | }
222 |
223 | $default_date = new DateTime( '30 days ago', wp_timezone() );
224 |
225 | $query = wp_parse_args( $query, [
226 | 'before' => current_time( 'Y-m-d' ),
227 | 'after' => $default_date->format( 'Y-m-d' )
228 | ] );
229 |
230 | $clauses = [];
231 |
232 | foreach ( $query as $column => $value ) {
233 |
234 | if ( ! $this->is_valid_column( $column ) ) {
235 | continue;
236 | }
237 |
238 | switch ( $column ) {
239 | case 'before':
240 | $clauses[] = $wpdb->prepare( "s_date <= %s", $value );
241 | break;
242 | case 'after':
243 | $clauses[] = $wpdb->prepare( "s_date >= %s", $value );
244 | break;
245 | case 's_type':
246 | case 'location':
247 | case 'content':
248 | case 's_date':
249 | $clauses[] = $wpdb->prepare( "$column = %s", $value );
250 | break;
251 | default:
252 | $clauses[] = $wpdb->prepare( "$column = %d", $value );
253 | break;
254 | }
255 | }
256 |
257 | $where = implode( ' AND ', $clauses );
258 |
259 | $query = "SELECT SUM(s_count) FROM $this->table_name WHERE $where";
260 |
261 | $count = intval( $wpdb->get_var( $query ) );
262 |
263 | wp_cache_set( $cache_key, $count, 'hollerbox:counts' );
264 |
265 | return $count;
266 | }
267 |
268 | /**
269 | * Get all impressions for all popups for the last 30 days
270 | *
271 | * @return int
272 | */
273 | public function get_total_impressions_last_30() {
274 | $after = new DateTime( '30 days ago' );
275 |
276 | return $this->_get_total_count_for_interval( [
277 | 's_type' => 'impression',
278 | 'after' => $after->format( 'Y-m-d' )
279 | ] );
280 | }
281 |
282 | /**
283 | * Get all conversions for all popups for the last 30 days
284 | *
285 | * @return int
286 | */
287 | public function get_total_conversions_last_30() {
288 | $after = new DateTime( '30 days ago' );
289 |
290 | return $this->_get_total_count_for_interval( [
291 | 's_type' => 'conversion',
292 | 'after' => $after->format( 'Y-m-d' )
293 | ] );
294 | }
295 |
296 | /**
297 | * Get the impression count for a given interval
298 | *
299 | * @param $popup Holler_Popup
300 | * @param $interval DateInterval
301 | *
302 | * @return int
303 | */
304 | public function get_total_impressions_for_interval( Holler_Popup $popup, DateInterval $interval ) {
305 | return $this->get_total_popup_count_for_interval( 'impression', $popup, $interval );
306 | }
307 |
308 | /**
309 | * Get the submission count for a given interval
310 | *
311 | * @param $popup Holler_Popup
312 | * @param $interval DateInterval
313 | *
314 | * @return int
315 | */
316 | public function get_total_conversions_for_interval( Holler_Popup $popup, DateInterval $interval ) {
317 | return $this->get_total_popup_count_for_interval( 'conversion', $popup, $interval );
318 | }
319 |
320 | /**
321 | * Ensures that a column is valid for SQL queries
322 | *
323 | * @param $column
324 | *
325 | * @return bool
326 | */
327 | public function is_valid_column( $column ) {
328 | return in_array( $column, [
329 | 's_type',
330 | 's_count',
331 | 'popup_id',
332 | 'location',
333 | 's_date',
334 | 'content'
335 | ] );
336 | }
337 |
338 | /**
339 | * Get rows of report data for the given query
340 | *
341 | * @param array $query
342 | *
343 | * @return array
344 | */
345 | public function get_report_data( array $query = [] ) {
346 |
347 | global $wpdb;
348 |
349 | $default_date = new DateTime( '30 days ago', wp_timezone() );
350 |
351 | $query = wp_parse_args( $query, [
352 | 'before' => current_time( 'Y-m-d' ),
353 | 'after' => $default_date->format( 'Y-m-d' )
354 | ] );
355 |
356 | $clauses = [];
357 |
358 | foreach ( $query as $column => $value ) {
359 | switch ( $column ) {
360 | case 'before':
361 | $clauses[] = $wpdb->prepare( 's_date <= %s', $value );
362 | break;
363 | case 'after':
364 | $clauses[] = $wpdb->prepare( 's_date >= %s', $value );
365 | break;
366 | case 's_type':
367 | case 'location':
368 | case 'content':
369 | case 's_date':
370 | $clauses[] = $wpdb->prepare( "$column = %s", $value );
371 | break;
372 | default:
373 | if ( $this->is_valid_column( $column ) ) {
374 | if ( is_numeric( $column ) ) {
375 | $clauses[] = $wpdb->prepare( "$column = %d", $value );
376 | } else {
377 | $clauses[] = $wpdb->prepare( "$column = %s", $value );
378 | }
379 | }
380 | break;
381 | }
382 | }
383 |
384 | $where = implode( ' AND ', $clauses );
385 |
386 | $query = "SELECT * FROM $this->table_name WHERE $where";
387 |
388 | return $wpdb->get_results( $query );
389 | }
390 |
391 | /**
392 | * Max key length
393 | *
394 | * @return int
395 | */
396 | public function max_key_length() {
397 | global $wpdb;
398 |
399 | return $wpdb->charset === 'utf8mb4' ? 191 : 255;
400 | }
401 |
402 | /**
403 | * Change location to varchar 255
404 | * Update primary key to include location
405 | *
406 | * @return void
407 | */
408 | public function update_2_1_2() {
409 | global $wpdb;
410 |
411 | $max_index_length = $this->max_key_length();
412 |
413 | $wpdb->query( "ALTER TABLE {$this->table_name} MODIFY COLUMN location varchar($max_index_length) NOT NULL, DROP PRIMARY KEY, ADD PRIMARY KEY (popup_id, s_type, s_date, location);" );
414 | }
415 |
416 | /**
417 | * Add the new column
418 | *
419 | * @return void
420 | */
421 | public function update_2_2() {
422 | global $wpdb;
423 |
424 | $max_index_length = $this->max_key_length();
425 |
426 | $commands = [
427 | // Change the engine to InnoDB
428 | "ALTER TABLE {$this->table_name} ENGINE=InnoDB;",
429 | // Add the content columns
430 | "ALTER TABLE {$this->table_name} ADD content varchar($max_index_length) NOT NULL;",
431 | // Add index
432 | "CREATE INDEX content ON {$this->table_name} (content);",
433 | // Update the primary key
434 | "ALTER TABLE {$this->table_name} DROP PRIMARY KEY, ADD PRIMARY KEY (popup_id, s_type, s_date, location, content);"
435 | ];
436 |
437 | foreach ( $commands as $command ) {
438 | $wpdb->query( $command );
439 | }
440 | }
441 |
442 | }
443 |
--------------------------------------------------------------------------------
/includes/class-holler-settings.php:
--------------------------------------------------------------------------------
1 | settings = get_option( self::OPTION_NAME, [] );
34 | }
35 |
36 | /**
37 | * Get a setting
38 | *
39 | * @param string|array $setting
40 | * @param mixed $default
41 | *
42 | * @return mixed
43 | */
44 | public function get( $setting, $default = false ) {
45 |
46 | if ( is_array( $setting ) ) {
47 |
48 | $settings = [];
49 |
50 | foreach ( $setting as $key ) {
51 | $settings[ $key ] = $this->settings[ $key ] ?? ( is_array( $default ) && isset( $default[ $key ] ) ? $default[ $key ] : false );
52 | }
53 |
54 | return $settings;
55 | }
56 |
57 | return $this->settings[ $setting ] ?? $default;
58 | }
59 |
60 | /**
61 | * Update a setting
62 | *
63 | * @param $name string
64 | * @param $value mixed
65 | * @param $commit bool
66 | *
67 | * @return void
68 | */
69 | public function update( string $name, $value, bool $commit = true ) {
70 | $this->settings[ $name ] = $value;
71 |
72 | switch ( $name ) {
73 | case 'stacked_delay':
74 | $value = absint( $value );
75 | break;
76 | case 'cookie_compliance':
77 | case 'gdpr_enabled':
78 | case 'credit_disabled':
79 | case 'disable_all':
80 | case 'script_debug_mode':
81 | case 'delete_all_data':
82 | case 'telemetry_subscribed':
83 | case 'is_licensed':
84 | case 'is_legacy_user':
85 | case 'legacy_user_agreed':
86 | $value = boolval( $value );
87 | break;
88 | case 'gdpr_text':
89 | $value = wp_kses_post( $value );
90 | break;
91 | case 'cookie_name':
92 | case 'cookie_value':
93 | default:
94 | $value = sanitize_text_field( $value );
95 | break;
96 | }
97 |
98 | $this->settings[ $name ] = $value;
99 |
100 | if ( $commit ) {
101 | $this->commit();
102 | }
103 | }
104 |
105 | /**
106 | * Commit the settings as they are in the instance
107 | *
108 | * @return bool
109 | */
110 | public function commit() {
111 | return update_option( self::OPTION_NAME, $this->settings );
112 | }
113 |
114 | /**
115 | * Drop the option name
116 | * @return void
117 | */
118 | public function drop() {
119 | delete_option( self::OPTION_NAME );
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/includes/class-holler-telemetry.php:
--------------------------------------------------------------------------------
1 | WP_REST_Server::CREATABLE,
38 | 'callback' => [ $this, 'optin' ],
39 | 'permission_callback' => [ $this, 'permission_callback' ]
40 | ],
41 | ] );
42 |
43 | register_rest_route( 'hollerbox', '/telemetry/legacy', [
44 | [
45 | 'methods' => WP_REST_Server::CREATABLE,
46 | 'callback' => [ $this, 'optin_legacy' ],
47 | 'permission_callback' => [ $this, 'permission_callback' ]
48 | ],
49 | ] );
50 |
51 | }
52 |
53 | /**
54 | * Send telemetry weekly
55 | *
56 | * @return void
57 | */
58 | public function send_telemetry() {
59 |
60 | // Opted out of telemetry
61 | if ( ! Holler_Settings::instance()->get( 'telemetry_subscribed' ) ) {
62 | return;
63 | }
64 |
65 | $request = [
66 | 'email' => Holler_Settings::instance()->get( 'telemetry_email' ),
67 | 'date' => current_time( 'mysql' ),
68 | 'system_info' => [
69 | 'php_version' => PHP_VERSION,
70 | 'wp_version' => get_bloginfo( 'version' ),
71 | 'hb_version' => HOLLERBOX_VERSION,
72 | 'site_lang' => get_bloginfo( 'language' ),
73 | ],
74 | 'usage' => [
75 | 'conversions' => Holler_Reporting::instance()->get_total_conversions_last_30(),
76 | 'impressions' => Holler_Reporting::instance()->get_total_impressions_last_30()
77 | ]
78 | ];
79 |
80 | wp_remote_post( 'https://hollerwp.com/wp-json/gh/v3/webhook-listener?auth_token=JVq8f3u&step_id=36', [
81 | 'body' => wp_json_encode( $request ),
82 | 'headers' => [
83 | 'Content-Type' => 'application/json'
84 | ],
85 | ] );
86 |
87 | }
88 |
89 | /**
90 | * Optin top telemetry
91 | *
92 | * @param WP_REST_Request $request
93 | *
94 | * @return WP_Error|WP_REST_Response
95 | */
96 | public function optin( WP_REST_Request $request ) {
97 |
98 | $telemetry = $request->get_param( 'telemetry_subscribed' ) ?: false;
99 | $marketing = $request->get_param( 'marketing_subscribed' ) ?: false;
100 | $email = sanitize_email( $request->get_param( 'email' ) );
101 |
102 | $user = wp_get_current_user();
103 | $name = $user->display_name;
104 |
105 | if ( ! $email ) {
106 | $email = $user->user_email;
107 | }
108 |
109 | if ( ! empty( $user->first_name ) ) {
110 | $name = $user->first_name . ' ' . $user->last_name;
111 | }
112 |
113 | if ( ! $telemetry && ! $marketing ) {
114 | return rest_ensure_response( [ 'success' => true ] );
115 | }
116 |
117 | $request = [
118 | 'email' => $email,
119 | 'name' => $name,
120 | 'role' => sanitize_text_field( $request->get_param( 'role' ) ),
121 | 'business' => sanitize_text_field( $request->get_param( 'business' ) ),
122 | 'marketing' => $marketing ? 'yes' : 'no',
123 | 'telemetry' => $telemetry ? 'yes' : 'no'
124 | ];
125 |
126 | if ( $telemetry ) {
127 | // Remember telemetry optin for later
128 | Holler_Settings::instance()->update( 'telemetry_subscribed', true );
129 | Holler_Settings::instance()->update( 'telemetry_email', $email );
130 |
131 | $request['system_info'] = [
132 | 'php_version' => PHP_VERSION,
133 | 'wp_version' => get_bloginfo( 'version' ),
134 | 'hb_version' => HOLLERBOX_VERSION,
135 | 'site_lang' => get_bloginfo( 'language' ),
136 | ];
137 | }
138 |
139 | wp_remote_post( 'https://hollerwp.com/wp-json/gh/v3/webhook-listener?auth_token=JVq8f3u&step_id=34', [
140 | 'body' => wp_json_encode( $request ),
141 | 'headers' => [
142 | 'Content-Type' => 'application/json'
143 | ],
144 | ] );
145 |
146 | return rest_ensure_response( [ 'success' => true ] );
147 | }
148 |
149 | /**
150 | * Optin top telemetry
151 | *
152 | * @param WP_REST_Request $request
153 | *
154 | * @return WP_Error|WP_REST_Response
155 | */
156 | public function optin_legacy( WP_REST_Request $request ) {
157 |
158 | $email = sanitize_email( $request->get_param( 'email' ) );
159 | $name = sanitize_text_field( $request->get_param( 'name' ) );
160 |
161 | $request = [
162 | 'email' => $email,
163 | 'name' => $name,
164 | ];
165 |
166 | wp_remote_post( 'https://hollerwp.com/wp-json/gh/v3/webhook-listener?auth_token=NdZ6FeU&step_id=44', [
167 | 'body' => wp_json_encode( $request ),
168 | 'headers' => [
169 | 'Content-Type' => 'application/json'
170 | ],
171 | ] );
172 |
173 | return rest_ensure_response( [ 'success' => true ] );
174 | }
175 |
176 | public function permission_callback() {
177 | return current_user_can( 'manage_options' );
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/includes/class-holler-updater.php:
--------------------------------------------------------------------------------
1 | [ $this, 'v_2_0' ],
12 | '2.1.2' => [ $this, 'v_2_1_2' ],
13 | '2.2' => [ $this, 'v_2_2' ],
14 | ];
15 | }
16 |
17 | public function v_2_2() {
18 | Holler_Reporting::instance()->update_2_2();
19 | }
20 |
21 | /**
22 | * Updated the stats table
23 | *
24 | * @return void
25 | */
26 | public function v_2_1_2() {
27 | Holler_Reporting::instance()->update_2_1_2();
28 | }
29 |
30 | /**
31 | * Upate to 2.0
32 | *
33 | * @return void
34 | */
35 | public function v_2_0() {
36 |
37 | // Migrate some settings over
38 | Holler_Settings::instance()->update( 'license', get_option( 'hwp_pro_edd_license' ), false );
39 | Holler_Settings::instance()->update( 'is_licensed', get_option( 'hwp_pro_edd_license_status' ) === 'valid', false );
40 | Holler_Settings::instance()->update( 'credit_disabled', get_option( 'hwp_powered_by' ), false );
41 |
42 | $options = [
43 | 'hwp_ac_api_key',
44 | 'hwp_ck_api_key',
45 | 'hwp_mc_api_key',
46 | 'hwp_powered_by',
47 | ];
48 |
49 | // If any of the settings were set and are not empty, this person is a legacy user
50 | foreach ( $options as $option ) {
51 | $val = get_option( $option );
52 | if ( ! empty( $val ) ) {
53 | Holler_Settings::instance()->update( 'is_legacy_user', true, false );
54 | break;
55 | }
56 | }
57 |
58 | // Commit the settings
59 | Holler_Settings::instance()->commit();
60 |
61 | // Create the reports table
62 | Holler_Reporting::instance()->create_table();
63 | }
64 |
65 | /**
66 | * Array of updates which have already been performed
67 | *
68 | * @return false|mixed|void
69 | */
70 | public function get_previous_updates() {
71 | return get_option( 'holler_previous_updates', [] );
72 | }
73 |
74 | /**
75 | * Whether an update for a specific version was performed
76 | *
77 | * @param $version
78 | *
79 | * @return bool
80 | */
81 | public function did_update( $version ) {
82 | return in_array( $version, $this->get_previous_updates() );
83 | }
84 |
85 | /**
86 | * Remember that we did this update
87 | *
88 | * @param $version
89 | *
90 | * @return void
91 | */
92 | public function update_complete( $version ) {
93 | $updates = $this->get_previous_updates();
94 | $updates[] = $version;
95 | update_option( 'holler_previous_updates', $updates );
96 | }
97 |
98 | /**
99 | * Maybe perform updates
100 | *
101 | * @return void
102 | */
103 | public function maybe_upgrade() {
104 | foreach ( $this->get_updates() as $update => $callback ) {
105 | if ( $this->did_update( $update ) ) {
106 | continue;
107 | }
108 |
109 | if ( is_callable( $callback ) ) {
110 | call_user_func( $callback );
111 |
112 | $this->update_complete( $update );
113 | }
114 | }
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/languages/holler-box.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/groundhoggwp/holler-box/bff676c0eddee90de2adf6852b411e5e08148e7b/languages/holler-box.mo
--------------------------------------------------------------------------------
/languages/holler-box.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Project-Id-Version: Holler Box\n"
4 | "POT-Creation-Date: 2018-09-15 13:14-0800\n"
5 | "PO-Revision-Date: 2018-09-15 13:14-0800\n"
6 | "Last-Translator: \n"
7 | "Language-Team: \n"
8 | "MIME-Version: 1.0\n"
9 | "Content-Type: text/plain; charset=UTF-8\n"
10 | "Content-Transfer-Encoding: 8bit\n"
11 | "X-Generator: Poedit 1.5.7\n"
12 | "X-Poedit-KeywordsList: _;gettext;gettext_noop;__;_e\n"
13 | "X-Poedit-Basepath: .\n"
14 | "X-Poedit-SearchPath-0: /Users/scottopolis/Documents/Websites/Flywheel Local/"
15 | "app/public/wp-content/plugins/holler-box\n"
16 |
17 | #: /Users/scottopolis/Documents/Websites/Flywheel
18 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-functions.php:130
19 | msgid "Please enter a valid email address."
20 | msgstr ""
21 |
22 | #: /Users/scottopolis/Documents/Websites/Flywheel
23 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-functions.php:324
24 | msgid "Type your message"
25 | msgstr ""
26 |
27 | #: /Users/scottopolis/Documents/Websites/Flywheel
28 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-functions.php:399
29 | msgid "50% Complete"
30 | msgstr ""
31 |
32 | #: /Users/scottopolis/Documents/Websites/Flywheel
33 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-functions.php:582
34 | msgid "Enter email"
35 | msgstr ""
36 |
37 | #: /Users/scottopolis/Documents/Websites/Flywheel
38 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:202
39 | msgid "Settings"
40 | msgstr ""
41 |
42 | #: /Users/scottopolis/Documents/Websites/Flywheel
43 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:252
44 | msgid "Email Settings"
45 | msgstr ""
46 |
47 | #: /Users/scottopolis/Documents/Websites/Flywheel
48 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:254
49 | msgid "Email title (only used with \"send to email\" setting) "
50 | msgstr ""
51 |
52 | #: /Users/scottopolis/Documents/Websites/Flywheel
53 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:258
54 | msgid ""
55 | "If you are using ConvertKit, entery your API key. It can be found on your account info page. "
58 | msgstr ""
59 |
60 | #: /Users/scottopolis/Documents/Websites/Flywheel
61 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:262
62 | msgid ""
63 | "If you are using Active Campaign, enter your url and API key. It can be "
64 | "found under My Settings -> Developer."
65 | msgstr ""
66 |
67 | #: /Users/scottopolis/Documents/Websites/Flywheel
68 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:268
69 | msgid ""
70 | "If you are using MailChimp, enter your API key. It can be found under "
71 | "Account -> Extras -> API Keys."
72 | msgstr ""
73 |
74 | #: /Users/scottopolis/Documents/Websites/Flywheel
75 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:274
76 | msgid ""
77 | "Disable MailChimp double-opt in? Check to subscribe users to your list "
78 | "without confirmation. If checked, MailChimp will not send a final welcome "
79 | "email."
80 | msgstr ""
81 |
82 | #: /Users/scottopolis/Documents/Websites/Flywheel
83 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:277
84 | msgid "Miscellaneous"
85 | msgstr ""
86 |
87 | #: /Users/scottopolis/Documents/Websites/Flywheel
88 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:281
89 | msgid "Hide attribution links"
90 | msgstr ""
91 |
92 | #: /Users/scottopolis/Documents/Websites/Flywheel
93 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:365
94 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:366
95 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:367
96 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:368
97 | msgid "Holler Box"
98 | msgstr ""
99 |
100 | #: /Users/scottopolis/Documents/Websites/Flywheel
101 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:369
102 | msgid "Add New"
103 | msgstr ""
104 |
105 | #: /Users/scottopolis/Documents/Websites/Flywheel
106 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:370
107 | msgid "Add New Box"
108 | msgstr ""
109 |
110 | #: /Users/scottopolis/Documents/Websites/Flywheel
111 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:371
112 | msgid "New Box"
113 | msgstr ""
114 |
115 | #: /Users/scottopolis/Documents/Websites/Flywheel
116 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:372
117 | msgid "Edit Box"
118 | msgstr ""
119 |
120 | #: /Users/scottopolis/Documents/Websites/Flywheel
121 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:373
122 | msgid "View Box"
123 | msgstr ""
124 |
125 | #: /Users/scottopolis/Documents/Websites/Flywheel
126 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:374
127 | msgid "All Boxes"
128 | msgstr ""
129 |
130 | #: /Users/scottopolis/Documents/Websites/Flywheel
131 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:375
132 | msgid "Search Boxes"
133 | msgstr ""
134 |
135 | #: /Users/scottopolis/Documents/Websites/Flywheel
136 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:376
137 | msgid "Parent Boxes:"
138 | msgstr ""
139 |
140 | #: /Users/scottopolis/Documents/Websites/Flywheel
141 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:377
142 | msgid "No Boxes found."
143 | msgstr ""
144 |
145 | #: /Users/scottopolis/Documents/Websites/Flywheel
146 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:378
147 | msgid "No Boxes found in Trash."
148 | msgstr ""
149 |
150 | #: /Users/scottopolis/Documents/Websites/Flywheel
151 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:413
152 | msgid "Display"
153 | msgstr ""
154 |
155 | #: /Users/scottopolis/Documents/Websites/Flywheel
156 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:422
157 | msgid "Advanced Settings"
158 | msgstr ""
159 |
160 | #: /Users/scottopolis/Documents/Websites/Flywheel
161 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:444
162 | msgid "Choose a Holler Box Type"
163 | msgstr ""
164 |
165 | #: /Users/scottopolis/Documents/Websites/Flywheel
166 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:541
167 | msgid "Position"
168 | msgstr ""
169 |
170 | #: /Users/scottopolis/Documents/Websites/Flywheel
171 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:564
172 | msgid "Choose a Template"
173 | msgstr ""
174 |
175 | #: /Users/scottopolis/Documents/Websites/Flywheel
176 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:604
177 | msgid "Popup Options"
178 | msgstr ""
179 |
180 | #: /Users/scottopolis/Documents/Websites/Flywheel
181 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:608
182 | msgid "Upload a Custom Image"
183 | msgstr ""
184 |
185 | #: /Users/scottopolis/Documents/Websites/Flywheel
186 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:621
187 | msgid "Accent color"
188 | msgstr ""
189 |
190 | #: /Users/scottopolis/Documents/Websites/Flywheel
191 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:625
192 | msgid "Background color"
193 | msgstr ""
194 |
195 | #: /Users/scottopolis/Documents/Websites/Flywheel
196 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:628
197 | msgid "Text color"
198 | msgstr ""
199 |
200 | #: /Users/scottopolis/Documents/Websites/Flywheel
201 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:637
202 | msgid "Show email opt-in"
203 | msgstr ""
204 |
205 | #: /Users/scottopolis/Documents/Websites/Flywheel
206 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:645
207 | msgid "Send to email address"
208 | msgstr ""
209 |
210 | #: /Users/scottopolis/Documents/Websites/Flywheel
211 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:649
212 | msgid "ConvertKit"
213 | msgstr ""
214 |
215 | #: /Users/scottopolis/Documents/Websites/Flywheel
216 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:653
217 | msgid "MailChimp"
218 | msgstr ""
219 |
220 | #: /Users/scottopolis/Documents/Websites/Flywheel
221 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:657
222 | msgid "Active Campaign"
223 | msgstr ""
224 |
225 | #: /Users/scottopolis/Documents/Websites/Flywheel
226 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:661
227 | msgid "Drip"
228 | msgstr ""
229 |
230 | #: /Users/scottopolis/Documents/Websites/Flywheel
231 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:667
232 | msgid "MailPoet"
233 | msgstr ""
234 |
235 | #: /Users/scottopolis/Documents/Websites/Flywheel
236 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:673
237 | msgid "Custom"
238 | msgstr ""
239 |
240 | #: /Users/scottopolis/Documents/Websites/Flywheel
241 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:681
242 | msgid ""
243 | "ConvertKit List ID, click for help. "
246 | "*required "
247 | msgstr ""
248 |
249 | #: /Users/scottopolis/Documents/Websites/Flywheel
250 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:687
251 | msgid "MailChimp List *required"
252 | msgstr ""
253 |
254 | #: /Users/scottopolis/Documents/Websites/Flywheel
255 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:720
256 | msgid "Active Campaign List *required"
257 | msgstr ""
258 |
259 | #: /Users/scottopolis/Documents/Websites/Flywheel
260 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:752
261 | msgid "MailPoet List *required "
262 | msgstr ""
263 |
264 | #: /Users/scottopolis/Documents/Websites/Flywheel
265 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:784
266 | msgid "Send to email *required "
267 | msgstr ""
268 |
269 | #: /Users/scottopolis/Documents/Websites/Flywheel
270 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:791
271 | msgid "Insert HTML form code here"
272 | msgstr ""
273 |
274 | #: /Users/scottopolis/Documents/Websites/Flywheel
275 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:801
276 | msgid "Name Field Placeholder"
277 | msgstr ""
278 |
279 | #: /Users/scottopolis/Documents/Websites/Flywheel
280 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:807
281 | msgid "Don't show first name field"
282 | msgstr ""
283 |
284 | #: /Users/scottopolis/Documents/Websites/Flywheel
285 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:813
286 | msgid "Small text above email field"
287 | msgstr ""
288 |
289 | #: /Users/scottopolis/Documents/Websites/Flywheel
290 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:818
291 | msgid "Placeholder"
292 | msgstr ""
293 |
294 | #: /Users/scottopolis/Documents/Websites/Flywheel
295 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:823
296 | msgid "Confirmation Message"
297 | msgstr ""
298 |
299 | #: /Users/scottopolis/Documents/Websites/Flywheel
300 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:828
301 | msgid "Submit Button Text"
302 | msgstr ""
303 |
304 | #: /Users/scottopolis/Documents/Websites/Flywheel
305 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:959
306 | msgid "What pages?"
307 | msgstr ""
308 |
309 | #: /Users/scottopolis/Documents/Websites/Flywheel
310 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:966
311 | msgid "Show on pages"
312 | msgstr ""
313 |
314 | #: /Users/scottopolis/Documents/Websites/Flywheel
315 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:978
316 | msgid "Show to these visitors"
317 | msgstr ""
318 |
319 | #: /Users/scottopolis/Documents/Websites/Flywheel
320 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:981
321 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:992
322 | msgid "All visitors"
323 | msgstr ""
324 |
325 | #: /Users/scottopolis/Documents/Websites/Flywheel
326 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:982
327 | msgid "Logged in only"
328 | msgstr ""
329 |
330 | #: /Users/scottopolis/Documents/Websites/Flywheel
331 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:983
332 | msgid "Logged out only"
333 | msgstr ""
334 |
335 | #: /Users/scottopolis/Documents/Websites/Flywheel
336 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:989
337 | msgid "New or returning"
338 | msgstr ""
339 |
340 | #: /Users/scottopolis/Documents/Websites/Flywheel
341 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:993
342 | msgid "New visitors only"
343 | msgstr ""
344 |
345 | #: /Users/scottopolis/Documents/Websites/Flywheel
346 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:994
347 | msgid "Returning visitors only"
348 | msgstr ""
349 |
350 | #: /Users/scottopolis/Documents/Websites/Flywheel
351 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1001
352 | msgid "When should we show it?"
353 | msgstr ""
354 |
355 | #: /Users/scottopolis/Documents/Websites/Flywheel
356 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1005
357 | msgid "Immediately"
358 | msgstr ""
359 |
360 | #: /Users/scottopolis/Documents/Websites/Flywheel
361 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1006
362 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1023
363 | msgid "Delay of"
364 | msgstr ""
365 |
366 | #: /Users/scottopolis/Documents/Websites/Flywheel
367 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1006
368 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1023
369 | msgid "seconds"
370 | msgstr ""
371 |
372 | #: /Users/scottopolis/Documents/Websites/Flywheel
373 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1007
374 | msgid "User scrolls halfway down the page"
375 | msgstr ""
376 |
377 | #: /Users/scottopolis/Documents/Websites/Flywheel
378 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1008
379 | msgid "Exit Detection"
380 | msgstr ""
381 |
382 | #: /Users/scottopolis/Documents/Websites/Flywheel
383 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1018
384 | msgid "After it displays, when should it disappear?"
385 | msgstr ""
386 |
387 | #: /Users/scottopolis/Documents/Websites/Flywheel
388 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1022
389 | msgid "When user clicks hide"
390 | msgstr ""
391 |
392 | #: /Users/scottopolis/Documents/Websites/Flywheel
393 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1031
394 | msgid "How often should we show it to each visitor?"
395 | msgstr ""
396 |
397 | #: /Users/scottopolis/Documents/Websites/Flywheel
398 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1035
399 | msgid "Hide after user interacts (Close or email submit)"
400 | msgstr ""
401 |
402 | #: /Users/scottopolis/Documents/Websites/Flywheel
403 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1036
404 | msgid "Every page load"
405 | msgstr ""
406 |
407 | #: /Users/scottopolis/Documents/Websites/Flywheel
408 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1037
409 | msgid "Show, then hide for"
410 | msgstr ""
411 |
412 | #: /Users/scottopolis/Documents/Websites/Flywheel
413 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1037
414 | msgid "days"
415 | msgstr ""
416 |
417 | #: /Users/scottopolis/Documents/Websites/Flywheel
418 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1044
419 | msgid "Show on Devices"
420 | msgstr ""
421 |
422 | #: /Users/scottopolis/Documents/Websites/Flywheel
423 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1048
424 | msgid "All devices"
425 | msgstr ""
426 |
427 | #: /Users/scottopolis/Documents/Websites/Flywheel
428 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1049
429 | msgid "Desktop only"
430 | msgstr ""
431 |
432 | #: /Users/scottopolis/Documents/Websites/Flywheel
433 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1050
434 | msgid "Mobile only"
435 | msgstr ""
436 |
437 | #: /Users/scottopolis/Documents/Websites/Flywheel
438 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1059
439 | msgid "Hide the floating button? (Appears when box is hidden.)"
440 | msgstr ""
441 |
442 | #: /Users/scottopolis/Documents/Websites/Flywheel
443 | #: Local/app/public/wp-content/plugins/holler-box/includes/class-holler-admin.php:1068
444 | msgid "Gravatar Email"
445 | msgstr ""
446 |
--------------------------------------------------------------------------------
/uninstall.php:
--------------------------------------------------------------------------------
1 | get( 'delete_all_data' ) ) {
36 |
37 | \Holler_Reporting::instance()->drop();
38 |
39 | // Delete all the posts
40 | $wpdb->query( "DELETE p,tr,pm
41 | FROM $wpdb->posts p
42 | LEFT JOIN $wpdb->term_relationships tr
43 | ON (p.ID = tr.object_id)
44 | LEFT JOIN $wpdb->postmeta pm
45 | ON (p.ID = pm.post_id)
46 | WHERE p.post_type = 'hollerbox';" );
47 |
48 | // Delete cached user meta
49 | $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key in ('hollerbox_popup_conversions','hollerbox_closed_popups');" );
50 |
51 | \Holler_Settings::instance()->drop();
52 |
53 | wp_clear_scheduled_hook( 'hollerbox/telemetry' );
54 |
55 | }
56 |
--------------------------------------------------------------------------------