Skip to content

Commit 2c30023

Browse files
committed
Allow to start/unstar stored segment
1 parent e1e415e commit 2c30023

File tree

6 files changed

+157
-24
lines changed

6 files changed

+157
-24
lines changed

core/Updates/5.6.0-b2.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/**
4+
* Matomo - free/libre analytics platform
5+
*
6+
* @link https://matomo.org
7+
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8+
*/
9+
10+
namespace Piwik\Updates;
11+
12+
use Piwik\Updater;
13+
use Piwik\Updater\Migration\Factory as MigrationFactory;
14+
use Piwik\Updates;
15+
16+
class Updates_5_6_0_b2 extends Updates
17+
{
18+
/**
19+
* @var MigrationFactory
20+
*/
21+
private $migration;
22+
23+
public function __construct(MigrationFactory $factory)
24+
{
25+
$this->migration = $factory;
26+
}
27+
28+
public function getMigrations(Updater $updater)
29+
{
30+
return [
31+
$this->migration->db->addColumn('segment', 'starred', 'TINYINT(1) NOT NULL DEFAULT 0'),
32+
];
33+
}
34+
35+
public function doUpdate(Updater $updater)
36+
{
37+
$updater->executeMigrations(__FILE__, $this->getMigrations($updater));
38+
}
39+
}

core/Version.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ final class Version
2222
* The current Matomo version.
2323
* @var string
2424
*/
25-
public const VERSION = '5.6.0-b1';
25+
public const VERSION = '5.6.0-b2';
2626

2727
public const MAJOR_VERSION = 5;
2828

plugins/SegmentEditor/API.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ public function add(
329329
'enable_only_idsite' => (int) $idSite,
330330
'auto_archive' => (int) $autoArchive,
331331
'ts_created' => Date::now()->getDatetime(),
332+
'starred' => 0,
332333
'deleted' => 0,
333334
);
334335

@@ -348,6 +349,36 @@ public function add(
348349
return $id;
349350
}
350351

352+
/**
353+
* Stars a stored segment.
354+
*
355+
* @param int $idSegment
356+
* @throws Exception if the user is not logged in or does not have the required permissions.
357+
*/
358+
public function star(int $idSegment): void
359+
{
360+
$segment = $this->getSegmentOrFail($idSegment);
361+
$this->checkUserCanEditOrDeleteSegment($segment);
362+
$bind = array('starred' => 1);
363+
364+
$this->getModel()->updateSegment($idSegment, $bind);
365+
}
366+
367+
/**
368+
* Unstars a stored segment.
369+
*
370+
* @param int $idSegment
371+
* @throws Exception if the user is not logged in or does not have the required permissions.
372+
*/
373+
public function unstar(int $idSegment): void
374+
{
375+
$segment = $this->getSegmentOrFail($idSegment);
376+
$this->checkUserCanEditOrDeleteSegment($segment);
377+
$bind = array('starred' => 0);
378+
379+
$this->getModel()->updateSegment($idSegment, $bind);
380+
}
381+
351382
/**
352383
* Returns a stored segment by ID
353384
*

plugins/SegmentEditor/Model.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ public static function install()
282282
`auto_archive` tinyint(4) NOT NULL default 0,
283283
`ts_created` TIMESTAMP NULL,
284284
`ts_last_edit` TIMESTAMP NULL,
285+
`starred` tinyint(4) NOT NULL default 0,
285286
`deleted` tinyint(4) NOT NULL default 0,
286287
PRIMARY KEY (`idsegment`)";
287288

plugins/SegmentEditor/javascripts/Segmentation.js

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -211,21 +211,35 @@ Segmentation = (function($) {
211211
}
212212

213213

214-
injClass = "";
214+
injClass = [];
215215
var checkSelected = segment.definition;
216+
var escapedSegmentName = (segment.definition).replace(/"/g, '&quot;');
216217

217-
if( checkSelected == self.currentSegmentStr ||
218-
checkSelected == decodeURIComponent(self.currentSegmentStr)
219-
) {
220-
injClass = 'class="segmentSelected"';
218+
if (checkSelected === self.currentSegmentStr || checkSelected === decodeURIComponent(self.currentSegmentStr)) {
219+
injClass.push('segmentSelected');
220+
}
221+
if (segment.starred) {
222+
injClass.push('segmentStarred');
221223
}
222-
listHtml += '<li data-idsegment="'+segment.idsegment+'" data-definition="'+ (segment.definition).replace(/"/g, '&quot;') +'" '
223-
+injClass+' title="'+ getSegmentTooltipEnrichedWithUsername(segment) +'"><span class="segname" tabindex="4">'+getSegmentName(segment)+'</span>';
224-
if(self.segmentAccess == "write") {
225-
listHtml += '<span class="editSegment" title="'+ self.translations['General_Edit'].toLocaleLowerCase() +'"></span>';
224+
listHtml += '' +
225+
'<li class="' + injClass.join(' ') + '"' +
226+
'data-idsegment="' + segment.idsegment + '"' +
227+
'data-definition="' + escapedSegmentName + '"' +
228+
'title="' + getSegmentTooltipEnrichedWithUsername(segment) + '"' +
229+
'>' +
230+
'<span class="segname" tabindex="4">' + getSegmentName(segment) + '</span>';
231+
if (self.segmentAccess === "write") {
232+
listHtml += '' +
233+
'<button data-star class="starSegment">️' +
234+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24">' +
235+
'<path stroke="black" stroke-width="3" fill="none" d="M9.153 5.408C10.42 3.136 11.053 2 12 2c.947 0 1.58 1.136 2.847 3.408l.328.588c.36.646.54.969.82 1.182.28.213.63.292 1.33.45l.636.144c2.46.557 3.689.835 3.982 1.776.292.94-.546 1.921-2.223 3.882l-.434.507c-.476.557-.715.836-.822 1.18-.107.345-.071.717.001 1.46l.066.677c.253 2.617.38 3.925-.386 4.506-.766.582-1.918.051-4.22-1.009l-.597-.274c-.654-.302-.981-.452-1.328-.452-.347 0-.674.15-1.329.452l-.595.274c-2.303 1.06-3.455 1.59-4.22 1.01-.767-.582-.64-1.89-.387-4.507l.066-.676c.072-.744.108-1.116 0-1.46-.106-.345-.345-.624-.821-1.18l-.434-.508c-1.677-1.96-2.515-2.941-2.223-3.882.293-.941 1.523-1.22 3.983-1.776l.636-.144c.699-.158 1.048-.237 1.329-.45.28-.213.46-.536.82-1.182l.328-.588Z"/>' +
236+
'</svg>' +
237+
'</button>';
238+
listHtml += '<span class="editSegment" title="' + self.translations['General_Edit'].toLocaleLowerCase() + '"></span>';
226239
}
227-
if (comparisonService.isComparisonEnabled()
228-
|| comparisonService.isComparisonEnabled() === null // may not be initialized since this code is outside of Vue
240+
if (
241+
comparisonService.isComparisonEnabled() ||
242+
comparisonService.isComparisonEnabled() === null // may not be initialized since this code is outside of Vue
229243
) {
230244
listHtml += '<span class="compareSegment" title="' + _pk_translate('SegmentEditor_CompareThisSegment') + '"></span>';
231245
}
@@ -405,6 +419,27 @@ Segmentation = (function($) {
405419
e.preventDefault();
406420
});
407421

422+
self.target.on('click', '[data-star]', function (e) {
423+
e.stopPropagation();
424+
e.preventDefault();
425+
const $root = $(this).closest('li');
426+
const idSegment = $root.data('idsegment');
427+
const segment = getSegmentFromId(idSegment);
428+
segment.starred = !segment.starred;
429+
const method = segment.starred ? 'star' : 'unstar';
430+
$root.toggleClass('segmentStarred', segment.starred);
431+
432+
var ajaxHandler = new ajaxHelper();
433+
ajaxHandler.addParams({
434+
"module": 'API',
435+
"format": 'json',
436+
"method": 'SegmentEditor.' + method,
437+
"userLogin": piwik.userLogin,
438+
"idSegment": idSegment,
439+
}, 'GET');
440+
ajaxHandler.send();
441+
});
442+
408443
self.target.on('click', '.compareSegment', function (e) {
409444
e.stopPropagation();
410445
e.preventDefault();

plugins/SegmentEditor/stylesheets/segmentation.less

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ div.scrollable {
233233
}
234234

235235
.segmentationContainer .submenu ul {
236+
display: flex;
237+
flex-direction: column;
236238
color: @theme-color-text-light;
237239
float: none;
238240
font-size: 11px;
@@ -243,11 +245,19 @@ div.scrollable {
243245
padding-top: 10px;
244246
}
245247

246-
247248
.segmentationContainer .submenu ul li {
248249
padding: 2px 0 2px 0;
249250
margin: 3px 0 0 0;
250251
cursor: pointer;
252+
order: 2;
253+
}
254+
255+
.segmentationContainer .submenu ul li[data-idsegment=""] {
256+
order: 0;
257+
}
258+
259+
.segmentationContainer .submenu ul li.segmentStarred {
260+
order: 1;
251261
}
252262

253263
.segmentationContainer .submenu ul li:hover,
@@ -269,18 +279,25 @@ div.scrollable {
269279
}
270280

271281
.segmentationContainer ul.submenu > li {
272-
span.editSegment, span.compareSegment {
273-
display: block;
274-
float: right;
275-
text-align: center;
276-
margin-right: 4px;
277-
font-weight: normal;
282+
span.editSegment,
283+
span.compareSegment,
284+
.starSegment {
285+
flex: none;
278286
width: 16px;
279287
height: 16px;
280-
.opacity(0.5);
288+
289+
// Button reset
290+
padding: 0;
291+
border: 0;
292+
background: transparent;
293+
cursor: pointer;
294+
295+
font-weight: normal;
296+
text-align: center;
297+
opacity: 0.5;
281298

282299
&:hover {
283-
.opacity(1);
300+
opacity: 1;
284301
}
285302
}
286303

@@ -289,13 +306,22 @@ div.scrollable {
289306
order: 3;
290307
}
291308

309+
.starSegment {
310+
order: 2;
311+
}
312+
313+
.segmentStarred .starSegment path {
314+
fill: black;
315+
}
316+
292317
span.compareSegment {
293318
background: url(plugins/Morpheus/images/compare.svg) no-repeat;
294319
background-size: cover;
295320
order: 2;
296321

297322
&.allVisitsCompareSegment {
298-
margin-right: 24px;
323+
margin-left: 20px;
324+
margin-right: 20px;
299325
}
300326
}
301327

@@ -395,6 +421,8 @@ html.comparisonsDisabled .segmentationContainer ul.submenu {
395421

396422
li {
397423
display: flex;
424+
align-items: center;
425+
gap: 4px;
398426
}
399427
}
400428

@@ -520,9 +548,8 @@ a.metric_category {
520548
}
521549

522550
.segname {
523-
width: ~"calc(100% - 40px)";
551+
flex: auto;
524552
padding-right: 10px;
525-
display: inline-block;
526553
order: 1;
527554
}
528555

0 commit comments

Comments
 (0)