diff --git a/client/package.json b/client/package.json
index 2a08c002..d0eeea56 100644
--- a/client/package.json
+++ b/client/package.json
@@ -75,6 +75,7 @@
"localStorage": "^1.0.3",
"lodash": "^4.17.15",
"messageformat": "^0.2.2",
+ "moment": "^2.27.0",
"qs": "^6.5.2",
"query-string": "^6.12.1",
"quill-image-resize-module-react": "^3.0.0",
diff --git a/client/src/app-components/ticket-query-filters.js b/client/src/app-components/ticket-query-filters.js
index a914359d..fd63453b 100644
--- a/client/src/app-components/ticket-query-filters.js
+++ b/client/src/app-components/ticket-query-filters.js
@@ -9,8 +9,6 @@ import API from 'lib-app/api-call';
import history from 'lib-app/history';
import searchTicketsUtils from 'lib-app/search-tickets-utils';
-import DateTransformer from 'lib-core/date-transformer';
-
import Form from 'core-components/form';
import SubmitButton from 'core-components/submit-button';
import FormField from 'core-components/form-field';
@@ -19,10 +17,6 @@ import Button from 'core-components/button';
import Loading from 'core-components/loading';
-const INITIAL_PAGE = 1;
-
-const DEFAULT_START_DATE = 20170101;
-
class TicketQueryFilters extends React.Component {
static propTypes = {
@@ -59,7 +53,7 @@ class TicketQueryFilters extends React.Component {
+ fieldProps={{defaultValue: formState.dateRange}} />
@@ -149,7 +148,6 @@ class AdminPanelSystemPreferences extends React.Component {
'url': form['url'],
'title': form['title'],
'layout': form['layout'] ? 'full-width' : 'boxed',
- 'time-zone': form['time-zone'],
'maintenance-mode': form['maintenance-mode'] * 1,
'allow-attachments': form['allow-attachments'] * 1,
'max-size': form['max-size'],
@@ -190,7 +188,6 @@ class AdminPanelSystemPreferences extends React.Component {
'url': result.data['url'],
'title': result.data['title'],
'layout': (result.data['layout'] == 'full-width') ? 1 : 0,
- 'time-zone': result.data['time-zone'],
'maintenance-mode': !!(result.data['maintenance-mode'] * 1),
'allow-attachments': !!(result.data['allow-attachments'] * 1),
'max-size': result.data['max-size'],
diff --git a/client/src/app/admin/panel/staff/staff-editor.js b/client/src/app/admin/panel/staff/staff-editor.js
index ce6d56b3..7bd37aa5 100644
--- a/client/src/app/admin/panel/staff/staff-editor.js
+++ b/client/src/app/admin/panel/staff/staff-editor.js
@@ -109,7 +109,7 @@ class StaffEditor extends React.Component {
{i18n('DEPARTMENTS')}
- {(!this.props.myAccount) ? this.renderDepartmentsForm() : this.renderDepartmentsInfo()}
+ {(this.props.myAccount && this.props.level !== 3) ? this.renderDepartmentsInfo() : this.renderDepartmentsForm()}
@@ -193,7 +193,7 @@ class StaffEditor extends React.Component {
renderDepartmentsInfo() {
return (
);
}
@@ -262,7 +262,6 @@ class StaffEditor extends React.Component {
departmentIndexes.push(index);
}
});
-
return departmentIndexes;
}
diff --git a/client/src/app/admin/panel/tickets/admin-panel-search-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-search-tickets.js
index 912207d6..b8e0dfdc 100644
--- a/client/src/app/admin/panel/tickets/admin-panel-search-tickets.js
+++ b/client/src/app/admin/panel/tickets/admin-panel-search-tickets.js
@@ -41,7 +41,6 @@ export function updateSearchTicketsFromURL() {
searchTicketsUtils.prepareFiltersForAPI(listConfig.filters)
));
});
-
}
}
diff --git a/client/src/core-components/date-range.js b/client/src/core-components/date-range.js
index 240fd5a4..5b2b94e7 100644
--- a/client/src/core-components/date-range.js
+++ b/client/src/core-components/date-range.js
@@ -33,18 +33,22 @@ class DateRange extends React.Component {
}
onChange(date, dateValue) {
+ if(dateValue !== "") {
+ dateValue = dateValue*10000;
+ dateValue = (date === "startDate") ? dateValue : dateValue+2359;
+ } else {
+ dateValue = 0;
+ }
const value = _.clone(this.props.value);
value[date] = dateValue;
- value.valid =
- value.startDate !== 0 &&
- value.endDate !== 0 && this.dateCompare({startDate: value.startDate, endDate: value.endDate});
+ value.valid = this.dateCompare({startDate: value.startDate, endDate: value.endDate});
this.props.onChange(value);
}
dateCompare(dateRange) {
- const { defaultValue, } = this.props;
- let startDate = dateRange.startDate === "" ? defaultValue.startDate : dateRange.startDate;
- let endDate = dateRange.endDate === "" ? defaultValue.endDate : dateRange.endDate;
+ const { defaultValue } = this.props;
+ const startDate = dateRange.startDate ? dateRange.startDate : defaultValue.startDate;
+ const endDate = dateRange.endDate ? dateRange.endDate : defaultValue.endDate;
let isValidRange = startDate <= endDate;
return isValidRange;
}
diff --git a/client/src/data/fixtures/system-fixtures.js b/client/src/data/fixtures/system-fixtures.js
index 76d9f00a..dd90f55f 100755
--- a/client/src/data/fixtures/system-fixtures.js
+++ b/client/src/data/fixtures/system-fixtures.js
@@ -13,7 +13,6 @@ module.exports = [
'url': 'http://www.opensupports.com/support',
'title': 'Support Center',
'layout': 'boxed',
- 'time-zone': 3,
'server-email': 'shitr@post.com',
'smtp-host': 'localhost',
'smtp-port': '7070',
diff --git a/client/src/lib-app/search-tickets-utils.js b/client/src/lib-app/search-tickets-utils.js
index 8ab4a4d4..ba3a5cc9 100644
--- a/client/src/lib-app/search-tickets-utils.js
+++ b/client/src/lib-app/search-tickets-utils.js
@@ -4,6 +4,8 @@ import _ from 'lodash';
import DateTransformer from 'lib-core/date-transformer';
import API from 'lib-app/api-call';
+const DEFAULT_UTC_START_DATE = 201701010000;
+
const TICKET_STATUSES = {
ANY: undefined,
OPENED: 0,
@@ -81,6 +83,7 @@ export default {
} :
filters
);
+ const dateRange = filtersForAPI.dateRange;
if(filtersForAPI && filtersForAPI.closed !== undefined) {
filtersForAPI = {
@@ -91,14 +94,11 @@ export default {
filtersForAPI = {
...filtersForAPI,
- dateRange: filtersForAPI.dateRange ? filtersForAPI.dateRange : this.getDefaultDateRangeForFilters()
+ dateRange: dateRange ? dateRange : this.getDefaultUTCRange()
}
return filtersForAPI ? filtersForAPI : {};
},
- getDefaultDateRangeForFilters() {
- return JSON.stringify(DateTransformer.formDateRangeToFilters([20170101, DateTransformer.getDateToday()]));
- },
getFiltersForURL(filtersWithShouldRemoveParams) {
const shouldRemoveCustomParam = filtersWithShouldRemoveParams.shouldRemoveCustomParam ? filtersWithShouldRemoveParams.shouldRemoveCustomParam : false;
const shouldRemoveUseInitialValuesParam = filtersWithShouldRemoveParams.shouldRemoveUseInitialValuesParam ? filtersWithShouldRemoveParams.shouldRemoveUseInitialValuesParam : false;
@@ -148,6 +148,13 @@ export default {
return closedDropdownIndex;
},
transformToFormValue(filters) {
+ const localDateRange = DateTransformer.rangeTransformer(JSON.parse(filters.dateRange), "UTCToLocal");
+ const newDateRange = {
+ valid: true,
+ startDate: localDateRange[0],
+ endDate: localDateRange[1],
+ };
+
return {
...filters,
query: filters.query ? filters.query : '',
@@ -155,7 +162,7 @@ export default {
departments: JSON.parse(filters.departments),
owners: JSON.parse(filters.owners),
tags: JSON.parse(filters.tags),
- dateRange: DateTransformer.dateRangeToFormValue(filters.dateRange),
+ dateRange: newDateRange,
authors: filters.authors ? JSON.parse(filters.authors) : [],
};
},
@@ -177,7 +184,7 @@ export default {
},
formValueToListConfig(form, hasAllAuthorsInfo = false) {
const authors = form.authors ? form.authors.map(author => ({id: author.id*1, isStaff: author.isStaff})) : [];
- const dateRangeFilter = [form.dateRange.startDate, form.dateRange.endDate];
+ const localRange = [form.dateRange.startDate, form.dateRange.endDate];
return {
filters: {
@@ -187,11 +194,25 @@ export default {
departments: form.departments !== undefined ? JSON.stringify(form.departments) : '[]',
owners: JSON.stringify(form.owners),
tags: JSON.stringify(form.tags),
- dateRange: JSON.stringify(DateTransformer.formDateRangeToFilters(dateRangeFilter)),
+ dateRange: JSON.stringify(DateTransformer.rangeTransformer(localRange, "localToUTC")),
authors: JSON.stringify(authors),
},
hasAllAuthorsInfo
};
+ },
+ getDefaultUTCRange() {
+ return JSON.stringify([DEFAULT_UTC_START_DATE, this.getDefaultUTCEndDate()]);
+ },
+ getDefaultUTCStartDate() {
+ return DEFAULT_UTC_START_DATE
+ },
+ getDefaultUTCEndDate() {
+ return DateTransformer.localDateToUTCNumericDate(JSON.stringify((DateTransformer.getDateToday()*10000)+2359));
+ },
+ getDefaultLocalStartDate() {
+ return DateTransformer.UTCDateToLocalNumericDate(this.getDefaultUTCStartDate())
+ },
+ getDefaultlocalEndDate() {
+ return DateTransformer.UTCDateToLocalNumericDate(this.getDefaultUTCEndDate())
}
-
-}
\ No newline at end of file
+}
diff --git a/client/src/lib-core/date-transformer.js b/client/src/lib-core/date-transformer.js
index 4d10a3e8..76effd4a 100644
--- a/client/src/lib-core/date-transformer.js
+++ b/client/src/lib-core/date-transformer.js
@@ -1,20 +1,33 @@
-let month = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
+import moment from 'moment';
+
+const stringDateFormat = 'YYYYMMDDHHmm';
+const localUTCMins = new Date().getTimezoneOffset();
export default {
+ stringDateToMoment(date) {
+ return moment(`${date}`, stringDateFormat);
+ },
+ momentToStringDate(date) {
+ return date.format(stringDateFormat);
+ },
+ UTCDateToLocalNumericDate(date) {
+ return JSON.parse(this.momentToStringDate(this.stringDateToMoment(date).subtract(localUTCMins, 'minutes')));
+ },
+ localDateToUTCNumericDate(date) {
+ return JSON.parse(this.momentToStringDate(this.stringDateToMoment(date).add(localUTCMins, 'minutes')));
+ },
+ rangeTransformer(range, trasformerFunctionKey) {
+ const trasformerDateFunction = {
+ UTCToLocal: this.UTCDateToLocalNumericDate.bind(this),
+ localToUTC: this.localDateToUTCNumericDate.bind(this)
+ }[trasformerFunctionKey];
+
+ return range.map((date) => {return trasformerDateFunction(JSON.stringify(date))});
+ },
transformToString(date, expressive = true) {
- date += ''; // Transform to string
- let y = date.substring(0, 4);
- let m = date.substring(4, 6);
- let d = date.substring(6, 8);
- m = (m[0] - '0') * 10 + (m[1] - '0');
-
- if(!expressive)
- return d + " " + month[m] + " " + y;
-
- let hr = date.substring(8, 10);
- let min = date.substring(10, 12);
-
- return d + " " + month[m] + " " + y + " at " + hr + ":" + min;
+ const momentDateLocal = this.stringDateToMoment(JSON.stringify(this.UTCDateToLocalNumericDate(date)));
+ if (expressive) momentDateLocal.format('D MMMM YYYY')
+ return momentDateLocal.format('D MMMM YYYY, HH:mm');
},
getDate(date) {
return date < 10 ? `0${date}` : `${date}`;
@@ -28,34 +41,4 @@ export default {
return newDate*1;
},
- getDefaultDateRange(range = undefined) {
- let newDateRange = range;
-
- if(range) {
- let dateRange = JSON.parse(range);
- let startDate = dateRange[0];
- let endDate = dateRange[1];
- let valid = true;
- newDateRange = {
- startDate: startDate,
- endDate: endDate,
- valid: valid
- }
- }
-
- return newDateRange;
- },
- formDateRangeToFilters(dateRange) {
- return [dateRange[0]*10000, dateRange[1]*10000+2400];
- },
- dateRangeToFormValue(_dateRange) {
- const dateRange = JSON.parse(_dateRange);
-
- return {
- valid: true,
- startDate: dateRange[0]/10000,
- endDate: (dateRange[1]-2400)/10000,
- };
- },
-
};
diff --git a/client/src/reducers/search-filters-reducer.js b/client/src/reducers/search-filters-reducer.js
index 2caf788e..d3b943f3 100644
--- a/client/src/reducers/search-filters-reducer.js
+++ b/client/src/reducers/search-filters-reducer.js
@@ -3,18 +3,15 @@ import queryString from 'query-string';
import Reducer from 'reducers/reducer';
-import DateTransformer from 'lib-core/date-transformer';
import searchTicketsUtils from '../lib-app/search-tickets-utils';
-const DEFAULT_START_DATE = 20170101;
-
const DEFAULT_FILTERS = {
query: undefined,
closed: undefined,
departments: '[]',
owners: '[]',
tags: '[]',
- dateRange: searchTicketsUtils.getDefaultDateRangeForFilters(),
+ dateRange: searchTicketsUtils.getDefaultUTCRange(),
orderBy: undefined,
authors: '[]',
};
@@ -33,7 +30,11 @@ class searchFiltersReducer extends Reducer {
owners: [],
tags: [],
authors: [],
- dateRange: {valid: true, startDate: DEFAULT_START_DATE, endDate: DateTransformer.getDateToday()}
+ dateRange: {
+ valid: true,
+ startDate: searchTicketsUtils.getDefaultLocalStartDate(),
+ endDate: searchTicketsUtils.getDefaultlocalEndDate()
+ }
},
ticketQueryListState : {
tickets: [],
diff --git a/server/controllers/system/edit-settings.php b/server/controllers/system/edit-settings.php
index 76acd679..30cb121a 100755
--- a/server/controllers/system/edit-settings.php
+++ b/server/controllers/system/edit-settings.php
@@ -16,7 +16,7 @@ DataValidator::with('CustomValidations', true);
*
* @apiParam {String} allowedLanguages The list of languages allowed.
* @apiParam {String} supportedLanguages The list of languages supported.
- * @apiParam {Setting} setting A setting can be any of the following: language, recaptcha-public, recaptcha-private, server-email, smtp-host, smtp-port, smtp-user, smtp-pass, time-zone, maintenance-mode, layout, allow-attachments, max-size, title, url.
+ * @apiParam {Setting} setting A setting can be any of the following: language, recaptcha-public, recaptcha-private, server-email, smtp-host, smtp-port, smtp-user, smtp-pass, maintenance-mode, layout, allow-attachments, max-size, title, url.
*
* @apiUse NO_PERMISSION
*
@@ -53,7 +53,6 @@ class EditSettingsController extends Controller {
'smtp-host',
'smtp-user',
'smtp-pass',
- 'time-zone',
'maintenance-mode',
'layout',
'allow-attachments',
diff --git a/server/controllers/system/get-settings.php b/server/controllers/system/get-settings.php
index d783d1f1..c6922e5b 100755
--- a/server/controllers/system/get-settings.php
+++ b/server/controllers/system/get-settings.php
@@ -38,7 +38,6 @@ class GetSettingsController extends Controller {
'language' => Setting::getSetting('language')->getValue(),
'reCaptchaKey' => Setting::getSetting('recaptcha-public')->getValue(),
'reCaptchaPrivate' => Setting::getSetting('recaptcha-private')->getValue(),
- 'time-zone' => Setting::getSetting('time-zone')->getValue(),
'maintenance-mode' => intval(Setting::getSetting('maintenance-mode')->getValue()),
'layout' => Setting::getSetting('layout')->getValue(),
'allow-attachments' => intval(Setting::getSetting('allow-attachments')->getValue()),
@@ -66,7 +65,6 @@ class GetSettingsController extends Controller {
$settingsList = [
'language' => Setting::getSetting('language')->getValue(),
'reCaptchaKey' => Setting::getSetting('recaptcha-public')->getValue(),
- 'time-zone' => Setting::getSetting('time-zone')->getValue(),
'maintenance-mode' => intval(Setting::getSetting('maintenance-mode')->getValue()),
'layout' => Setting::getSetting('layout')->getValue(),
'allow-attachments' => intval(Setting::getSetting('allow-attachments')->getValue()),
diff --git a/server/controllers/system/init-settings.php b/server/controllers/system/init-settings.php
index efda1177..88876ba5 100755
--- a/server/controllers/system/init-settings.php
+++ b/server/controllers/system/init-settings.php
@@ -78,7 +78,6 @@ class InitSettingsController extends Controller {
'smtp-host' => Controller::request('smtp-host'),
'smtp-user' => Controller::request('smtp-user'),
'smtp-pass' => Controller::request('smtp-pass'),
- 'time-zone' => 0,
'maintenance-mode' => 0,
'layout' => 'boxed',
'allow-attachments' => !!Controller::request('allow-attachments'),
diff --git a/server/index.php b/server/index.php
index c9531bb8..9f2c1070 100644
--- a/server/index.php
+++ b/server/index.php
@@ -2,6 +2,7 @@
@include 'config.php';
require_once 'vendor/autoload.php';
+date_default_timezone_set ('UTC');
// REDBEAN CONFIGURATION
use RedBeanPHP\Facade as RedBean;
diff --git a/tests/system/edit-settings.rb b/tests/system/edit-settings.rb
index 6e582f82..a6caf63f 100755
--- a/tests/system/edit-settings.rb
+++ b/tests/system/edit-settings.rb
@@ -7,7 +7,6 @@ describe'system/edit-settings' do
"csrf_userid" => $csrf_userid,
"csrf_token" => $csrf_token,
"maintenance-mode" => 0,
- "time-zone" => -3,
"layout" => 'full-width',
"allow-attachments" => 1,
"max-size" => 2,
@@ -21,9 +20,6 @@ describe'system/edit-settings' do
row = $database.getRow('setting', 'maintenance-mode', 'name')
(row['value']).should.equal('0')
- row = $database.getRow('setting', 'time-zone', 'name')
- (row['value']).should.equal('-3')
-
row = $database.getRow('setting', 'layout', 'name')
(row['value']).should.equal('full-width')