Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
shridhar-tl committed May 23, 2023
2 parents d904205 + 04fb8c4 commit 016ab28
Show file tree
Hide file tree
Showing 14 changed files with 163 additions and 103 deletions.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
}
},
"dependencies": {
"@atlaskit/avatar": "21.3.1",
"@atlaskit/side-navigation": "1.8.0",
"@atlaskit/avatar": "21.3.2",
"@atlaskit/side-navigation": "1.8.1",
"@coreui/coreui": "2.1.16",
"@forge/api": "^2.15.3",
"@forge/bridge": "^2.5.6",
Expand All @@ -75,7 +75,7 @@
"jquery": "3.7.0",
"jsd-report": "0.1.11",
"jspdf": "2.5.1",
"jspdf-autotable": "3.5.28",
"jspdf-autotable": "3.5.29",
"moment": "2.29.4",
"moment-timezone": "0.5.43",
"papaparse": "5.4.1",
Expand All @@ -90,15 +90,15 @@
"react-dnd": "14.0.4",
"react-dnd-html5-backend": "14.0.2",
"react-dom": "18.2.0",
"react-router-dom": "6.11.1",
"react-router-dom": "6.11.2",
"react-scripts": "5.0.1",
"reactstrap": "9.1.10",
"static-eval": "2.1.0"
},
"devDependencies": {
"@craco/craco": "^7.1.0",
"cross-env": "^7.0.3",
"eslint": "^8.40.0",
"eslint": "^8.41.0",
"eslint-plugin-react-hooks": "^4.6.0",
"gh-pages": "^5.0.0",
"sass": "^1.62.1",
Expand Down
4 changes: 2 additions & 2 deletions src/constants/api-urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export const ApiUrls = {
getIssueMetadata: "~/rest/api/2/issue/{0}/editmeta",
individualIssue: "~/rest/api/2/issue/{0}",
getAllIssueTypes: "~/rest/api/2/issuetype",
addIssueWorklog: "~/rest/api/2/issue/{0}/worklog?adjustEstimate=AUTO",
addIssueWorklog: "~/rest/api/2/issue/{0}/worklog",
issueWorklog: "~/rest/api/2/issue/{0}/worklog",
updateIndividualWorklog: "~/rest/api/2/issue/{0}/worklog/{1}?adjustEstimate=AUTO",
updateIndividualWorklog: "~/rest/api/2/issue/{0}/worklog/{1}",
individualWorklog: "~/rest/api/2/issue/{0}/worklog/{1}",
searchUser: "~/rest/api/2/user/search?maxResults={1}&startAt={2}&query={0}",
searchUser_Alt: "~/rest/api/2/user/search?maxResults={1}&startAt={2}&username={0}",
Expand Down
4 changes: 2 additions & 2 deletions src/content-scripts/jira-board.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { waitAndGet } from "./utils";

export async function applyBoardLogic(currentPage, settings, firstTime, applyModifications) {
if (currentPage === Pages.Board) {
$('.ghx-columns .ui-sortable div.js-issue .ja-issue-el').remove();
$('.ghx-columns div.js-issue .ja-issue-el').remove();

const triggerFunc = triggerWLTracking.bind({ settings, applyModifications });

const selector = '.ghx-columns .ui-sortable div.js-issue';
const selector = '.ghx-columns div.js-issue';
const issues = firstTime ? (await waitAndGet(selector)) : $(selector);
issues.each((i, el) => {
el = $(el);
Expand Down
135 changes: 72 additions & 63 deletions src/dialogs/AddWorklog.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import moment from 'moment';
import { InputMask } from 'primereact/inputmask';
import BaseDialog from './BaseDialog';
import { inject } from '../services/injector-service';
import { Button, Checkbox, DatePicker, TextBox } from '../controls';
import { Button, Checkbox, DatePicker, SelectBox, TextBox } from '../controls';
import { GadgetActionType } from '../gadgets';
import { EventCategory } from '../constants/settings';
import { IssuePicker } from '../jira-controls/IssuePicker';
Expand All @@ -17,6 +17,13 @@ function convertHours(value) {
return `${h.pad(2)}:${m.pad(2)}`;
}

const adjustEstimateTypes = [
{ value: '', label: 'Auto adjust' },
{ value: 'leave', label: 'No changes' },
{ value: 'manual', label: 'Reduce by' },
{ value: 'new', label: 'Set new estimate' }
];

class AddWorklog extends BaseDialog {
constructor(props) {
const { editTracker } = props;
Expand Down Expand Up @@ -66,8 +73,7 @@ class AddWorklog extends BaseDialog {
newState.log = {
ticketNo: obj.ticketNo,
dateStarted: moment(obj.startTime || obj.dateStarted || new Date()).toDate(),
description: obj.description?.trim() || '',
allowOverride: obj.allowOverride
description: obj.description?.trim() || ''
};

if (obj.parentId) {
Expand All @@ -80,17 +86,8 @@ class AddWorklog extends BaseDialog {
timeSpent = this.$utils.formatSecs(timeSpent, false, true);
}

if (!obj.allowOverride && timeSpent) {
newState.log.timeSpent = timeSpent;
}

if (timeSpent) {
newState.log.overrideTimeSpent = timeSpent;
}
else {
newState.log.overrideTimeSpent = this.defaultTimeSpent;
newState.log.allowOverride = true;
}
newState.log.timeSpent = timeSpent || this.defaultTimeSpent;

this.validateData(newState.log, newState.vald, newState.ctlClass);
}
Expand All @@ -106,10 +103,6 @@ class AddWorklog extends BaseDialog {
d.timeSpent = null;
}
}
if (d.overrideTimeSpent) {
d.overrideTimeSpent = d.overrideTimeSpent.substring(0, 5);
d.allowOverride = true;
}

if (copy) {
this.$analytics.trackEvent("Worklog copy", EventCategory.UserActions, (d.isUploaded ? "Uploaded worklog" : "Pending worklog"));
Expand All @@ -133,9 +126,8 @@ class AddWorklog extends BaseDialog {

// eslint-disable-next-line complexity
validateData(log, vald, ctlClass) {
if (log.allowOverride) {
log.overrideTimeSpent = log.overrideTimeSpent || log.timeSpent || "00:00";
}
log.timeSpent = log.overrideTimeSpent || log.timeSpent || "00:00";
delete log.overrideTimeSpent;

let validation = true;

Expand All @@ -147,20 +139,26 @@ class AddWorklog extends BaseDialog {
validation = (vald.dateStarted = ds.isValid() && ds.isBetween(startOfDay, new Date(), undefined, '[]')) && validation;
} else {
validation = (vald.dateStarted = !(!log.dateStarted || log.dateStarted.length < 16)) && validation;
vald.overrideTimeSpent = (log.allowOverride && log.overrideTimeSpent && log.overrideTimeSpent.length >= 4);
vald.overrideTimeSpent = vald.overrideTimeSpent && this.$worklog.getTimeSpent(log.overrideTimeSpent) > 0;
validation = (vald.overrideTimeSpent = vald.overrideTimeSpent || (!log.allowOverride && log.timeSpent && log.timeSpent.length >= 4)) && validation;
vald.timeSpent = (log.timeSpent && log.timeSpent.length >= 4);
vald.timeSpent = vald.timeSpent && this.$worklog.getTimeSpent(log.timeSpent) > 0;
validation = vald.timeSpent && validation;
const { adjustEstimate, estimate } = this.state;
vald.estimate = (!!estimate && this.$worklog.getTimeSpent(estimate) > 0) || !adjustEstimate || adjustEstimate === 'leave';
validation = vald.estimate && validation;
}

validation = (vald.description = this.minCommentLength < 1 || !(!log.description || log.description.length < this.minCommentLength)) && validation;
ctlClass.ticketNo = !vald.ticketNo ? 'is-invalid' : 'is-valid';
ctlClass.dateStarted = !vald.dateStarted ? 'is-invalid' : 'is-valid';
ctlClass.overrideTimeSpent = !vald.overrideTimeSpent ? 'is-invalid' : 'is-valid';
ctlClass.timeSpent = !vald.timeSpent ? 'is-invalid' : 'is-valid';
ctlClass.description = !vald.description ? 'is-invalid' : 'is-valid';
ctlClass.estimate = !vald.estimate ? 'is-invalid' : 'is-valid';

return validation;
}



saveWorklog = (worklog, vald, upload) => {
if (!this.validateData(worklog, vald, this.state.ctlClass)) {
this.$message.warning("Please provide value for all the mandatory fields", "Incomplete worklog details");
Expand All @@ -173,18 +171,26 @@ class AddWorklog extends BaseDialog {
const { dateStarted, description } = this.state.log;
this.$wltimer.editTrackerInfo(this.getTicketNo(this.state.log), dateStarted, description).then(this.props.onDone);
} else {
const { adjustEstimate, estimate } = this.state;
const timeSpent = worklog.overrideTimeSpent || worklog.timeSpent;

if (adjustEstimate) {
upload = { adjustEstimate, estimate };
}

this.$worklog.saveWorklog({
ticketNo: this.getTicketNo(worklog),
dateStarted: worklog.dateStarted,
overrideTimeSpent: worklog.overrideTimeSpent,
description: worklog.description,
worklogId: worklog.worklogId,
isUploaded: worklog.isUploaded,
timeSpent: worklog.timeSpent,
timeSpent,
parentId: worklog.parentId,
id: worklog.id
}, upload).then((result) => {
this.props.onDone(worklog.id > 0 ? { type: GadgetActionType.WorklogModified, edited: result, previousTime: this.previousTime } : { type: GadgetActionType.WorklogModified, added: result });
}, upload).then(result => {
this.props.onDone(worklog.id > 0 ?
{ type: GadgetActionType.WorklogModified, edited: result, previousTime: this.previousTime }
: { type: GadgetActionType.WorklogModified, added: result });
this.onHide();
}, (e) => {
this.setState({ isLoading: false });
Expand Down Expand Up @@ -242,11 +248,12 @@ class AddWorklog extends BaseDialog {

getFooter() {
const {
state: { isLoading, log, vald, uploadImmediately }
state: { isLoading, log, vald, uploadImmediately, adjustEstimate }
} = this;

return <>
{!log.id && <Checkbox checked={uploadImmediately} className="pull-left" label="Upload immediately to Jira" onChange={(chk) => this.setState({ uploadImmediately: chk })} />}
{!log.id && <Checkbox checked={uploadImmediately || !!adjustEstimate} disabled={!!adjustEstimate}
className="pull-left" label="Upload immediately to Jira" onChange={(chk) => this.setState({ uploadImmediately: chk })} />}
{log.id > 0 && <Button type="danger" icon="fa fa-trash-o" label="Delete" className="pull-left" disabled={isLoading} onClick={() => this.deleteWorklog(log)} />}
{log.id > 0 && !log.worklogId && <Button type="success" isLoading={isLoading} icon="fa fa-upload" label="Save & Upload" className="pull-left" disabled={isLoading}
onClick={() => this.saveWorklog(log, vald, true)} />}
Expand Down Expand Up @@ -275,24 +282,35 @@ class AddWorklog extends BaseDialog {
render() {
const {
minCommentLength,
state: { log, vald, ctlClass }
state: { log, vald, ctlClass, adjustEstimate, estimate },
props: { editTracker }
} = this;

if (!this.state.log) { return 'Loading...'; }

return super.renderBase(<div className="pad-22" onKeyPress={this.handleKeyPress}>
<div className="row pad-b">
<div className="col-sm-3">
<strong>Log time</strong>
<strong>Date started {editTracker ? '& Time spent' : ''}</strong>
</div>
<div className="p-col-9 col-sm-9">
<div className="col-lg-5 col-sm-6 col-xs-12">
<div className="form-group">
<div className={ctlClass.dateStarted}>
<DatePicker value={log.dateStarted} showTime={true} onChange={(val) => this.setValue("dateStarted", val)} />
</div>
<span className={`help-block ${vald.dateStarted ? '' : 'msg-error'}`}>Provide the time you had started the work</span>
</div>
</div>
{!editTracker && <div className="col-lg-3 col-sm-3 col-xs-12">
<div className="form-group no-margin">
<div className={`p-inputgroup ${ctlClass.timeSpent}`}>
<InputMask mask="99:99" className="w-80" value={log.timeSpent || ""} placeholder="00:00" maxlength={5}
onChange={(e) => this.setValue("timeSpent", e.value)} />
</div>
<span className={`help-block ${vald.timeSpent ? '' : 'msg-error'}`}>
Provide hours spent</span>
</div>
</div>}
</div>

<div className="row pad-b">
Expand All @@ -307,45 +325,36 @@ class AddWorklog extends BaseDialog {
</div>
</div>

{!this.props.editTracker && <div className="row pad-b">
<div className="col-sm-3">
<strong>Actual time spent</strong>
</div>
<div className="col-sm-2">
<strong>{this.formatTs(log.timeSpent) || '-'}</strong>
</div>
<div className="col-sm-4">
<strong>Override time spent</strong>
</div>
<div className="col-sm-3">
<div className="form-group no-margin">
<div className={`p-inputgroup ${ctlClass.overrideTimeSpent}`}>
<span className="p-inputgroup-addon">
<Checkbox checked={log.allowOverride || false} onChange={(val) => this.setValue("allowOverride", val)} />
</span>
<InputMask mask="99:99" className="w-80" value={log.overrideTimeSpent || ""} placeholder="00:00" maxlength={5} disabled={!log.allowOverride}
onChange={(e) => this.setValue("overrideTimeSpent", e.value)} />
</div>
</div>
</div>
<div className="col-sm-3"></div>
<div className="col-sm-9 no-t-padding">
<span className={`help-block ${vald.overrideTimeSpent ? '' : 'msg-error'}`}>
Provide the time spent on this task (override to change existing)</span>
</div>
</div>}

<div className="row">
<div className="col-sm-3">
<strong>Comments</strong>
<strong>Work description</strong>
</div>
<div className="col-sm-9">
<TextBox multiline={true} rows={5} value={log.description || ""} className={`form-control ${vald.description ? '' : 'ctl-error'}`}
<TextBox multiline={true} rows={3} value={log.description || ""} className={`form-control ${vald.description ? '' : 'ctl-error'}`}
onChange={(val) => this.setValue("description", val)}
placeholder={`Provide a brief info about the task you had done.${minCommentLength
? ` Should be atleast ${minCommentLength} chars is length. You can change this settings from General settings -> Worklog tab` : ''}`} />
</div>
</div>
<br />
{!editTracker && <div className="row pad-top-5">
<div className="col-sm-3">
<strong>Remaining estimate</strong>
</div>
<div className="col-sm-4">
<SelectBox value={adjustEstimate || ''} dataset={adjustEstimateTypes} onChange={adjustEstimate => this.setState({ adjustEstimate })} />
</div>
<div className="col-sm-4">
{(adjustEstimate === 'manual' || adjustEstimate === 'new') && <InputMask mask="99:99" className="w-80" value={estimate || ""} placeholder="00:00" maxlength={5}
onChange={(e) => this.setState({ estimate: e.value })} />}
</div>
{!!adjustEstimate && <>
<div className="col-sm-3"></div>
<div className="col-sm-9">
<span className="help-block"><strong>Note:</strong> Your worklog will be immediately uploaded upon save</span>
</div>
</>}
</div>}
</div>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/display-controls/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export {

export function getComponentFor(type) {
switch (type) {
case 'ageindays': return { Component: DateDisplay, props: { quick: true } };
case 'date': return { Component: DateDisplay, props: { dateOnly: true } };
case 'datetime': return { Component: DateDisplay };
case 'parent': return { Component: IssueDisplay, props: { settings: { valueType: 'both' } } };
Expand Down
5 changes: 1 addition & 4 deletions src/gadgets/PendingWorklog.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ class PendingWorklog extends BaseGadget {
w.rowClass = this.$utils.getRowStatus(w);
w.displayDate = this.$userutils.formatDateTime(w.dateStarted);
w.selected = selAllChk;
w.timeSpent = this.$utils.formatTs(w.timeSpent);
w.overrideTimeSpent = this.$utils.formatTs(w.overrideTimeSpent);
w.timeSpent = this.$utils.formatTs(w.overrideTimeSpent || w.timeSpent);
});

this.setState({ isLoading: false, worklogs });
Expand Down Expand Up @@ -155,7 +154,6 @@ class PendingWorklog extends BaseGadget {
<Column sortBy="summary">Assignee</Column>
<Column sortBy="dateStarted">Log Time</Column>
<Column sortBy="timeSpent">Time Spent</Column>
<Column sortBy="overrideTimeSpent">Override Time</Column>
<Column>Description</Column>
</tr>
</THead>
Expand All @@ -170,7 +168,6 @@ class PendingWorklog extends BaseGadget {
<td>{b.assignee}</td>
<td>{b.displayDate}</td>
<td>{b.timeSpent}</td>
<td>{b.overrideTimeSpent}</td>
<td>{b.description}</td>
</tr>}
</TBody>
Expand Down
3 changes: 3 additions & 0 deletions src/gadgets/WorklogReport/datastore.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const initialData = {
daysToHide: '1', // 1=show all days, 2=hide non working days,3=hide days without worklog
rIndicator: '1', // 1=thermometer, 2=bg highlight,0=none
timeZone: '1',
expandUsers: false,

sprintStartRounding: '1',
sprintEndRounding: '1',
Expand Down Expand Up @@ -84,6 +85,7 @@ export function getSettingsObj(data, opts) {
fields,
daysToHide,
rIndicator,
expandUsers,
jql,
logFilterType,
filterThrsType,
Expand Down Expand Up @@ -113,6 +115,7 @@ export function getSettingsObj(data, opts) {
fields,
daysToHide,
rIndicator,
expandUsers,
jql,
logFilterType,
filterThrsType,
Expand Down
Loading

0 comments on commit 016ab28

Please sign in to comment.