Skip to content

Commit ac0dd85

Browse files
fix(gitlab): update N4 custom script for new GitLab UI (#2407)
1 parent 33f6a6d commit ac0dd85

File tree

1 file changed

+126
-123
lines changed

1 file changed

+126
-123
lines changed

src/content/_custom_nf_gitlab.js

Lines changed: 126 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,145 @@
1-
//// START GITLAB
1+
/**
2+
* @name Custom Gitlab Script (N4)
3+
* @urlAlias nfGitlabScript
4+
* @urlRegex gitlab.com
5+
*/
6+
'use strict'
7+
8+
// ---------------------------
9+
// Issues (new GitLab UI)
10+
// ---------------------------
211
togglbutton.render(
3-
'.issue-details .detail-page-description:not(.toggl)',
4-
{ observe: !0 },
5-
function (t) {
6-
const n = [
7-
[a()]
8-
.filter(Boolean)
9-
.map(function (r) {
10-
return '#' + r;
11-
})
12-
.join(''),
13-
i(t),
14-
]
15-
.filter(Boolean)
16-
.join(' ');
17-
o($('.detail-page-header-actions'), n, !0), o($('.time-tracker'), n);
18-
}
19-
);
12+
'span[data-testid="work-item-created"]:not(.toggl)',
13+
{ observe: true },
14+
function (createdSpan) {
15+
if (!createdSpan) return
16+
createdSpan.classList.add('toggl')
17+
18+
const id = getIdFromBody()
19+
const prefix = id ? `#${id}` : ''
20+
21+
const titleEl = document.querySelector('[data-testid="work-item-title"]')
22+
const title = titleEl ? titleEl.textContent.trim() : ''
23+
24+
const description = [prefix, title].filter(Boolean).join(' ')
25+
26+
const link = togglbutton.createTimerLink({
27+
className: 'gitlab',
28+
description,
29+
tags: tagsSelector,
30+
taskId: (projects, tasks) => extractTaskId(projects, tasks),
31+
projectName: (projects, tasks) => extractProjectName(projects, tasks),
32+
})
33+
34+
createdSpan.insertAdjacentElement('afterend', link)
35+
},
36+
)
37+
38+
// ---------------------------
39+
// Merge Requests (new GitLab UI)
40+
// ---------------------------
2041
togglbutton.render(
21-
'.merge-request > .detail-page-header:not(.toggl)',
22-
{ observe: !0 },
23-
function (t) {
24-
const n = [
25-
[a()]
26-
.filter(Boolean)
27-
.map(function (r) {
28-
return 'MR' + r + '::';
29-
})
30-
.join(''),
31-
i(t),
32-
]
33-
.filter(Boolean)
34-
.join(' ');
35-
o($('.detail-page-header-actions'), n, !0), o($('.time-tracker'), n);
36-
}
37-
);
38-
function o(t, e, n = !1) {
39-
const r = togglbutton.createTimerLink({
40-
className: 'gitlab',
41-
description: e,
42-
tags: l,
43-
taskId: (o, i) => {
44-
return extractTaskId(o, i);
45-
},
46-
projectName: (o, i) => {
47-
return extractProjectName(o, i);
48-
},
49-
});
50-
n ? t.parentElement.insertBefore(r, t) : t.parentElement.appendChild(r, t);
51-
}
52-
function i(t) {
53-
const e = t.querySelector('.title');
54-
return e ? e.textContent.trim() : '';
55-
}
56-
function a() {
57-
const t = window.location.pathname,
58-
e = /-\/(issues|merge_requests)\/(?<id>\d+)/;
59-
return (e.test(t) ? t.match(e) : { groups: { id: '' } }).groups.id;
42+
'.detail-page-description:not(.toggl)',
43+
{ observe: true },
44+
function (descBlock) {
45+
if (!descBlock) return
46+
descBlock.classList.add('toggl')
47+
48+
const id = getIdFromBody()
49+
const prefix = id ? `MR${id}::` : ''
50+
51+
const titleEl = document.querySelector('[data-testid="title-content"]')
52+
const title = titleEl ? titleEl.textContent.trim() : ''
53+
54+
const description = [prefix, title].filter(Boolean).join(' ')
55+
56+
const link = togglbutton.createTimerLink({
57+
className: 'gitlab',
58+
description,
59+
tags: tagsSelector,
60+
taskId: (projects, tasks) => extractTaskId(projects, tasks),
61+
projectName: (projects, tasks) => extractProjectName(projects, tasks),
62+
})
63+
64+
descBlock.insertAdjacentElement('afterbegin', link)
65+
},
66+
)
67+
68+
// ---------------------------
69+
// Shared helpers
70+
// ---------------------------
71+
function getIdFromBody() {
72+
const body = document.querySelector('body')
73+
return body ? body.getAttribute('data-page-type-id') : ''
6074
}
61-
function s() {
62-
const t =
63-
$('.title .project-item-select-holder') ||
64-
$('.breadcrumbs-list li:nth-last-child(3) .breadcrumb-item-text');
65-
return t ? t.textContent.trim() : '';
75+
76+
function getProjectSelector() {
77+
const el = document.querySelector(
78+
'a[data-track-label="project_overview"] div[data-testid="nav-item-link-label"]',
79+
)
80+
return el ? el.textContent.trim() : ''
6681
}
67-
function l() {
68-
const t = document.querySelectorAll('div.labels span[data-qa-label-name]');
69-
if (!t) return [];
70-
const e = [];
71-
for (const n of Object.values(t)) {
72-
const r = n.getAttribute('data-qa-label-name');
73-
e.push(r);
82+
83+
function tagsSelector() {
84+
const nodeList = document.querySelectorAll(
85+
'[data-testid="selected-label-content"] span.gl-label-text',
86+
)
87+
88+
const tags = []
89+
for (const node of Object.values(nodeList || {})) {
90+
const tagName = (node.textContent || '').trim()
91+
if (tagName && !tags.includes(tagName)) tags.push(tagName)
7492
}
75-
return e;
93+
return tags
7694
}
7795

78-
////END GITLAB
79-
80-
////START HELPER
81-
const ExtractNFGitlabTogglTaskId = () => {
82-
debugger;
83-
let togglTaskId = null;
84-
let tags = l();
85-
const GITLAB_LABEL_REGEX = /togg(e|)l(::|:)/gim;
86-
const REMOVE_TRALING_LABEL_DESCRIPTION = / .*/;
87-
88-
debugger;
89-
if (Array.isArray(tags)) {
90-
tags.forEach((element) => {
91-
if (element.match(GITLAB_LABEL_REGEX)) {
92-
togglTaskId = element
93-
.replace(GITLAB_LABEL_REGEX, '')
94-
.toUpperCase()
95-
.replace(REMOVE_TRALING_LABEL_DESCRIPTION, '');
96-
return;
97-
}
98-
});
96+
function extractN4GitlabTogglTaskCode() {
97+
const tags = tagsSelector()
98+
if (!Array.isArray(tags) || tags.length === 0) return null
99+
100+
const GITLAB_LABEL_REGEX = /togg(e|)l(::|:)/gim
101+
const REMOVE_TRAILING_DESCRIPTION = / .*/
102+
103+
for (const tag of tags) {
104+
if (GITLAB_LABEL_REGEX.test(tag)) {
105+
// Reset regex lastIndex since we use 'g' flag
106+
GITLAB_LABEL_REGEX.lastIndex = 0
107+
return tag
108+
.replace(GITLAB_LABEL_REGEX, '')
109+
.toUpperCase()
110+
.replace(REMOVE_TRAILING_DESCRIPTION, '')
111+
.trim()
112+
}
99113
}
100-
return togglTaskId;
101-
};
114+
return null
115+
}
102116

103117
function extractTaskId(projects, tasks) {
104-
debugger;
105-
let nfTogglTask = ExtractNFGitlabTogglTaskId();
106-
if (nfTogglTask === null) {
107-
return {};
108-
}
118+
const code = extractN4GitlabTogglTaskCode()
119+
if (!code) return {}
109120

110-
const n = Object.keys(tasks).filter((o) =>
111-
tasks[o].name.startsWith(nfTogglTask)
112-
),
113-
s = n.length > 0 ? tasks[n[0]].id : {};
114-
return s;
121+
const keys = Object.keys(tasks || {})
122+
const matchKey = keys.find((k) => (tasks[k]?.name || '').startsWith(code))
123+
return matchKey ? tasks[matchKey].id : {}
115124
}
116125

117-
function extractTaskProjectId(nfTogglTask, projects, tasks) {
118-
if (nfTogglTask === null) {
119-
return null;
120-
}
126+
function extractTaskProjectId(code, projects, tasks) {
127+
if (!code) return null
121128

122-
const n = Object.keys(tasks).filter((o) =>
123-
tasks[o].name.startsWith(nfTogglTask)
124-
),
125-
s = n.length > 0 ? tasks[n[0]].project_id : null;
126-
console.log(s);
127-
return s;
129+
const keys = Object.keys(tasks || {})
130+
const matchKey = keys.find((k) => (tasks[k]?.name || '').startsWith(code))
131+
return matchKey ? tasks[matchKey].project_id : null
128132
}
129133

130134
function extractProjectName(projects, tasks) {
131-
debugger;
132-
let nfTogglTask = ExtractNFGitlabTogglTaskId();
133-
if (nfTogglTask === null) {
134-
return null;
135-
}
135+
const code = extractN4GitlabTogglTaskCode()
136+
137+
if (!code) return getProjectSelector() || null
138+
139+
const projectId = extractTaskProjectId(code, projects, tasks)
140+
if (!projectId) return getProjectSelector() || null
136141

137-
let projectID = extractTaskProjectId(nfTogglTask, projects, tasks);
138-
const n = Object.keys(projects).filter((o) => projects[o].id === projectID),
139-
s = n.length > 0 ? projects[n[0]].name : null;
140-
console.log(s);
141-
return s;
142+
const keys = Object.keys(projects || {})
143+
const matchKey = keys.find((k) => projects[k]?.id === projectId)
144+
return matchKey ? projects[matchKey].name : getProjectSelector() || null
142145
}

0 commit comments

Comments
 (0)