Skip to content

Commit 79243e2

Browse files
authored
Merge pull request #6208 from Countly/resolve-conflicts-24.05->24.10
Release.24.05
2 parents 4775082 + fe74bb7 commit 79243e2

16 files changed

Lines changed: 391 additions & 137 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11

22
## Version 24.10.x
33
Features:
4-
- [crashed] Fix unescaped SDK logs
4+
- [crashes] Fix unescaped SDK logs
55
- [dashboards] Added the option to set a refresh rate for dashboards, allowing data to update more frequently for selected dashboards
6-
- [star-rating] Added missing columns to Rating Widgets table edit
7-
- [ui] Fix alignment of drawers title and close icon
86
- [feedback] Uniformize drawer internal name input texts
7+
- [feedback] Uniformize feedback widgets status tag
8+
- [star-rating] Allow bulk update of widget status
99
- [star-rating] Fix rating score and responses table sorting
10+
- [ui] Fix alignment of drawers title and close icon
11+
- [UI] Remove white background from input character amount suffix
12+
13+
Enterprise Fixes:
14+
- [retention] Fixed report loading
1015

1116
## Version 24.10.9
1217
Fixes:

frontend/express/public/javascripts/countly/vue/components/dropdown.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@
613613
handleMenuItemClick: function(command, instance) {
614614
if (!this.disabled) {
615615
this.$emit('command', command, instance);
616-
this.$refs.dropdown.handleClose();
616+
this.$refs?.dropdown?.handleClose();
617617
}
618618
},
619619
toggleArrowState: function() {

frontend/express/public/javascripts/countly/vue/components/helpers.js

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,25 +86,63 @@
8686
}
8787
}));
8888

89-
Vue.component("cly-status-tag", countlyBaseComponent.extend({
90-
template: '<div class="cly-vue-status-tag" :class="dynamicClasses">\n' +
91-
'<div class="cly-vue-status-tag__blink"></div>\n' +
92-
'{{text}}\n' +
93-
'</div>',
94-
mixins: [countlyVue.mixins.i18n],
89+
Vue.component('cly-status-tag', countlyBaseComponent.extend({
9590
props: {
96-
text: { required: true, type: String },
97-
color: { default: "green", type: String},
98-
size: { default: "unset", type: String},
91+
color: {
92+
default: 'green',
93+
type: String
94+
},
95+
96+
loading: {
97+
default: false,
98+
type: Boolean
99+
},
100+
101+
size: {
102+
default: 'unset',
103+
type: String
104+
},
105+
106+
text: {
107+
required: true,
108+
type: String
109+
}
99110
},
111+
100112
computed: {
101-
dynamicClasses: function() {
102-
if (this.size === "small") {
103-
return ["cly-vue-status-tag--small", "cly-vue-status-tag--" + this.color];
113+
dynamicClasses() {
114+
const classes = [];
115+
116+
if (this.size === 'small') {
117+
classes.push('cly-vue-status-tag--small');
118+
}
119+
120+
if (this.loading) {
121+
classes.push('cly-vue-status-tag--gray');
104122
}
105-
return "cly-vue-status-tag--" + this.color;
123+
else {
124+
classes.push(`cly-vue-status-tag--${this.color}`);
125+
}
126+
127+
return classes;
106128
}
107129
},
130+
131+
template: `
132+
<div
133+
class="cly-vue-status-tag"
134+
:class="dynamicClasses"
135+
>
136+
<div class="cly-vue-status-tag__blink" />
137+
<div
138+
v-if="loading"
139+
class="cly-vue-status-tag__skeleton"
140+
/>
141+
<template v-else>
142+
{{ text }}
143+
</template>
144+
</div>
145+
`
108146
}));
109147

110148
Vue.component("cly-diff-helper", countlyBaseComponent.extend({

frontend/express/public/stylesheets/vue/clyvue.scss

Lines changed: 101 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -143,73 +143,125 @@
143143
}
144144

145145
.cly-vue-status-tag {
146-
padding-right: 16.33px;
147-
border-radius: 4px;
148146
display: inline-block;
149-
&--small {
150-
font-size: 12px;
151-
line-height: 18px;
152-
display: flex;
153-
align-items: baseline;
154-
font-weight: 500;
155-
}
156-
&--green {
157-
background-color: #EBFAEE;
158-
color: #12AF51;
159-
padding: 0px 6px;
147+
border-radius: 4px;
148+
padding: 0px 6px;
149+
150+
// .cly-vue-status-tag__blink
151+
&__blink {
152+
display: inline-block;
153+
position: relative;
154+
top: -1px;
155+
width: 6px;
156+
height: 6px;
157+
border-radius: 8px;
158+
vertical-align: middle;
159+
margin-right: 2px;
160+
animation: blinker 1.5s cubic-bezier(0.5, 0, 1, 1) infinite alternate;
160161
}
161-
&--green &__blink{
162-
background-color: #12AF51;
162+
163+
// .cly-vue-status-tag__skeleton
164+
&__skeleton {
165+
display: inline-block;
166+
position: relative;
167+
top: -1px;
168+
background-color: #BDBDBD;
169+
width: 40px;
170+
height: 4px;
171+
border-radius: 8px;
172+
vertical-align: middle;
173+
animation: blinker 1.5s cubic-bezier(0.5, 0, 1, 1) infinite alternate;
163174
}
175+
176+
// .cly-vue-status-tag--blue
164177
&--blue {
165178
background-color: #E6F0FB;
166179
color: #017AFF;
167-
padding: 0px 6px;
168-
}
169-
&--blue &__blink{
170-
background-color: #017AFF;
180+
181+
// .cly-vue-status-tag--blue .cly-vue-status-tag__blink
182+
& .cly-vue-status-tag__blink {
183+
background-color: #017AFF;
184+
}
171185
}
172-
&--yellow {
173-
background-color: #FCF5E5;
174-
color: #CDAD7A;
175-
padding: 0px 6px;
186+
187+
// .cly-vue-status-tag--gray
188+
&--gray {
189+
background-color: #F5F5F5;
190+
color: #BDBDBD;
191+
192+
// .cly-vue-status-tag--gray .cly-vue-status-tag__blink
193+
& .cly-vue-status-tag__blink {
194+
background-color: #BDBDBD;
195+
}
176196
}
177-
&--yellow &__blink{
178-
background-color: #CDAD7A;
197+
198+
// .cly-vue-status-tag--green
199+
&--green {
200+
background-color: #EBFAEE;
201+
color: #12AF51;
202+
203+
// .cly-vue-status-tag--green .cly-vue-status-tag__blink
204+
& .cly-vue-status-tag__blink {
205+
background-color: #12AF51;
206+
}
179207
}
208+
209+
// .cly-vue-status-tag--red
180210
&--red {
181211
background-color: #FBECE5;
182212
color: #D23F00;
183-
padding: 0px 6px;
184-
}
185-
&--red &__blink{
186-
background-color: #D23F00;
187-
}
188-
&--gray {
189-
background-color: #F5F5F5;
190-
color: #BDBDBD;
191-
padding: 0px 6px;
213+
214+
// .cly-vue-status-tag--red .cly-vue-status-tag__blink
215+
& .cly-vue-status-tag__blink {
216+
background-color: #D23F00;
217+
}
192218
}
193-
&--gray &__blink{
194-
background-color: #BDBDBD;
219+
220+
// .cly-vue-status-tag--small
221+
&--small {
222+
font-size: 12px;
223+
line-height: 18px;
224+
display: flex;
225+
align-items: baseline;
226+
font-weight: 500;
227+
228+
// .cly-vue-status-tag--small .cly-vue-status-tag__blink
229+
& .cly-vue-status-tag__blink {
230+
/*
231+
NOTE: This is a hack to make the blinking dot align with the blinking line
232+
the hole component styles should be redone when working on the new UI
233+
*/
234+
top: 1px;
235+
}
236+
237+
// .cly-vue-status-tag--small .cly-vue-status-tag__skeleton
238+
& .cly-vue-status-tag__skeleton {
239+
/*
240+
NOTE: This is a hack to make the blinking line align with the blinking dot
241+
the hole component styles should be redone when working on the new UI
242+
*/
243+
top: 0px;
244+
margin: 4px 0;
245+
}
195246
}
196-
&__blink {
197-
position: relative;
198-
top: -1px;
199-
width: 6px;
200-
height: 6px;
201-
border-radius: 8px;
202-
display: inline-block;
203-
vertical-align: middle;
204-
margin-right: 2px;
205-
animation: blinker 1.5s cubic-bezier(0.5, 0, 1, 1) infinite alternate;
247+
248+
// .cly-vue-status-tag--yellow
249+
&--yellow {
250+
background-color: #FCF5E5;
251+
color: #CDAD7A;
252+
253+
// .cly-vue-status-tag--yellow .cly-vue-status-tag__blink
254+
& .cly-vue-status-tag__blink {
255+
background-color: #CDAD7A;
256+
}
206257
}
258+
207259
@keyframes blinker {
208260
50% {
209-
opacity: 0;
261+
opacity: 0;
210262
}
211-
}
212-
}
263+
}
264+
}
213265

214266
.cly-vue-theme-clydef {
215267

plugins/star-rating/api/api.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,72 @@ function uploadFile(myfile, id, callback) {
920920
});
921921
}
922922
});
923+
924+
/**
925+
* @api {post} /i/feedback/widgets/status Bulk update feedback widgets
926+
* @apiName BulkUpdateWidgetStatus
927+
* @apiGroup Ratings
928+
*
929+
* @apiDescription Update the status (active/inactive) of multiple feedback widgets in a single operation
930+
* @apiPermission Update permission for star_rating feature
931+
* @apiBody {Object} data JSON object where keys are widget IDs and values are boolean status values
932+
*
933+
* @apiSuccessExample {json} Success Response:
934+
* HTTP/1.1 200 OK
935+
* {
936+
* "result": "Success"
937+
* }
938+
*
939+
* @apiErrorExample {json} Error - Invalid Data Format:
940+
* HTTP/1.1 500 Internal Server Error
941+
* {
942+
* "result": "Invalid parameter 'data'"
943+
* }
944+
*/
945+
plugins.register('/i/feedback/widgets/status', function(ob) {
946+
const { params } = ob || {};
947+
948+
validateUpdate(params, FEATURE_NAME, function() {
949+
let data = {};
950+
951+
try {
952+
data = JSON.parse(params.qstring.data);
953+
}
954+
catch (error) {
955+
common.returnMessage(params, 500, "Invalid parameter 'data'");
956+
return false;
957+
}
958+
959+
const hasToUpdate = data && Object.keys(data).length > 0;
960+
961+
if (!hasToUpdate) {
962+
common.returnMessage(params, 400, 'Nothing to update');
963+
return false;
964+
}
965+
966+
const bulk = common.db.collection('feedback_widgets').initializeUnorderedBulkOp();
967+
968+
for (const key in data) {
969+
const newStatusValue = data[key] === true || data[key] === 'true' ? true : false;
970+
971+
bulk.find({ _id: common.db.ObjectID(key) }).updateOne({ $set: { 'status': newStatusValue } });
972+
}
973+
974+
bulk.execute(function(error) {
975+
if (error) {
976+
log.e(error);
977+
common.returnMessage(params, 400, error);
978+
}
979+
else {
980+
common.returnMessage(params, 200, 'Success');
981+
plugins.dispatch('/systemlogs', { params: params, action: 'surveys_widget_status', data: data });
982+
}
983+
});
984+
});
985+
986+
return true;
987+
});
988+
923989
/**
924990
* @api {post} /i/feedback/widgets/create Create new widget
925991
* @apiName CreateRatingsWidget

plugins/star-rating/frontend/public/javascripts/countly.models.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@
4545
"links"
4646
];
4747

48+
starRatingPlugin.bulkUpdateWidgetStatus = (payload) => {
49+
return $.ajax({
50+
type: 'POST',
51+
url: `${countlyCommon.API_URL}/i/feedback/widgets/status`,
52+
data: {
53+
app_id: countlyCommon.ACTIVE_APP_ID,
54+
data: JSON.stringify(payload)
55+
},
56+
dataType: 'json'
57+
}, { disableAutoCatch: true });
58+
};
59+
4860
starRatingPlugin.extractWidgetProperties = function(props) {
4961
var data = widgetProperties.reduce(function(newData, key) {
5062
newData[key] = props[key];
@@ -295,4 +307,4 @@
295307
return _period;
296308
};
297309

298-
}(window.starRatingPlugin = window.starRatingPlugin || {}, jQuery));
310+
}(window.starRatingPlugin = window.starRatingPlugin || {}, jQuery));

0 commit comments

Comments
 (0)