From c00720d6a2803b934b74d035932d459a03916a23 Mon Sep 17 00:00:00 2001 From: Guillermo Giuliana Date: Fri, 28 Aug 2020 07:13:34 -0300 Subject: [PATCH] Minor GitHub bugs (#806) * text-validation to edit article content * shows only own department on my account * add moment and update date * Update date transformer * Delete time zone setting. * Use local date in date range component and utc date in date range filter. * Fix github comment. * Fix merge 'Fix filter show bug in ticket search when ordering'. * Fix merge 'Fix filter show bug in ticket search when ordering' second part. * Fix getDefaultUTCEndDate function. Co-authored-by: Ivan Diaz Co-authored-by: LautaroCesso --- client/package.json | 1 + .../app-components/ticket-query-filters.js | 57 ++++++--------- .../src/app/admin/panel/admin-panel-menu.js | 2 +- .../articles/admin-panel-view-article.js | 2 +- .../admin-panel-system-preferences.js | 3 - .../src/app/admin/panel/staff/staff-editor.js | 5 +- .../tickets/admin-panel-search-tickets.js | 1 - client/src/core-components/date-range.js | 16 +++-- client/src/data/fixtures/system-fixtures.js | 1 - client/src/lib-app/search-tickets-utils.js | 39 +++++++--- client/src/lib-core/date-transformer.js | 71 +++++++------------ client/src/reducers/search-filters-reducer.js | 11 +-- server/controllers/system/edit-settings.php | 3 +- server/controllers/system/get-settings.php | 2 - server/controllers/system/init-settings.php | 1 - server/index.php | 1 + tests/system/edit-settings.rb | 4 -- 17 files changed, 101 insertions(+), 119 deletions(-) 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}} />
{i18n('STATUS')} @@ -207,16 +201,6 @@ class TicketQueryFilters extends React.Component { this.props.dispatch(SearchFiltersActions.setDefaultFormValues()); } - dateRangeToFormValue(_dateRange) { - const dateRange = JSON.parse(_dateRange); - - return { - valid: true, - startDate: dateRange[0]/10000, - endDate: (dateRange[1]-2400)/10000, - }; - } - getDepartmentsItems() { const { departments, } = this.props; let departmentsList = departments.map(department => { @@ -321,7 +305,8 @@ class TicketQueryFilters extends React.Component { {...formState, orderBy: filters.orderBy, page: 1}, true ); - if(formEdited) { + + if(formEdited && formState.dateRange.valid) { const filtersForAPI = searchTicketsUtils.prepareFiltersForAPI(listConfigWithCompleteAuthorsList.filters); const currentPath = window.location.pathname; const urlQuery = searchTicketsUtils.getFiltersForURL({ @@ -351,25 +336,25 @@ class TicketQueryFilters extends React.Component { } onChangeForm(data) { - let newStartDate = data.dateRange.startDate === "" ? DEFAULT_START_DATE : data.dateRange.startDate; - let newEndDate = data.dateRange.endDate === "" ? DateTransformer.getDateToday() : data.dateRange.endDate; - let departmentsId = data.departments.map(department => department.id); - let staffsId = data.owners.map(staff => staff.id); - let tagsName = this.tagsNametoTagsId(data.tags); - let authors = data.authors.map(({name, id, isStaff, profilePic, color}) => ({name, id: id*1, isStaff, profilePic, color})); + const newStartDate = data.dateRange.startDate ? data.dateRange.startDate : searchTicketsUtils.getDefaultLocalStartDate(); + const newEndDate = data.dateRange.endDate ? data.dateRange.endDate : searchTicketsUtils.getDefaultlocalEndDate(); + const departmentsId = data.departments.map(department => department.id); + const staffsId = data.owners.map(staff => staff.id); + const tagsName = this.tagsNametoTagsId(data.tags); + const authors = data.authors.map(({name, id, isStaff, profilePic, color}) => ({name, id: id*1, isStaff, profilePic, color})); - this.onChangeFormState({ - ...data, - tags: tagsName, - owners: staffsId, - departments: departmentsId, - authors: authors, - dateRange: { - ...data.dateRange, - startDate: newStartDate, - endDate: newEndDate - } - }); + this.onChangeFormState({ + ...data, + tags: tagsName, + owners: staffsId, + departments: departmentsId, + authors: authors, + dateRange: { + ...data.dateRange, + startDate: newStartDate, + endDate: newEndDate + } + }); } getFormValue(form) { diff --git a/client/src/app/admin/panel/admin-panel-menu.js b/client/src/app/admin/panel/admin-panel-menu.js index aa97b0e9..0e3c07d0 100644 --- a/client/src/app/admin/panel/admin-panel-menu.js +++ b/client/src/app/admin/panel/admin-panel-menu.js @@ -3,7 +3,7 @@ import _ from 'lodash'; import {connect} from 'react-redux'; import i18n from 'lib-app/i18n'; -import searchTicketsUtils from '../../../lib-app/search-tickets-utils'; +import searchTicketsUtils from 'lib-app/search-tickets-utils'; import Menu from 'core-components/menu'; import queryString from 'query-string'; diff --git a/client/src/app/admin/panel/articles/admin-panel-view-article.js b/client/src/app/admin/panel/articles/admin-panel-view-article.js index cad751dd..fbacf303 100644 --- a/client/src/app/admin/panel/articles/admin-panel-view-article.js +++ b/client/src/app/admin/panel/articles/admin-panel-view-article.js @@ -97,7 +97,7 @@ class AdminPanelViewArticle extends React.Component {
- + ); } diff --git a/client/src/app/admin/panel/settings/admin-panel-system-preferences.js b/client/src/app/admin/panel/settings/admin-panel-system-preferences.js index d0a4cf5d..b3246018 100755 --- a/client/src/app/admin/panel/settings/admin-panel-system-preferences.js +++ b/client/src/app/admin/panel/settings/admin-panel-system-preferences.js @@ -58,7 +58,6 @@ class AdminPanelSystemPreferences extends React.Component {
-
@@ -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 (
- + this.state.departments.includes(index))}} /> ); } @@ -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')