"Fossies" - the Fresh Open Source Software Archive

Member "graylog2-server-4.2.0/graylog2-web-interface/src/views/components/searchbar/date-time-picker/AbsoluteTimeInput.tsx" (13 Oct 2021, 7564 Bytes) of package /linux/misc/graylog2-server-4.2.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) TSX (TypeScript with React) source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Copyright (C) 2020 Graylog, Inc.
    3  *
    4  * This program is free software: you can redistribute it and/or modify
    5  * it under the terms of the Server Side Public License, version 1,
    6  * as published by MongoDB, Inc.
    7  *
    8  * This program is distributed in the hope that it will be useful,
    9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   11  * Server Side Public License for more details.
   12  *
   13  * You should have received a copy of the Server Side Public License
   14  * along with this program. If not, see
   15  * <http://www.mongodb.com/licensing/server-side-public-license>.
   16  */
   17 import * as React from 'react';
   18 import { useRef } from 'react';
   19 import PropTypes from 'prop-types';
   20 import styled, { css } from 'styled-components';
   21 import moment from 'moment';
   22 
   23 import { Icon } from 'components/common';
   24 import { Button, FormGroup, InputGroup, FormControl } from 'components/graylog';
   25 import DateTime from 'logic/datetimes/DateTime';
   26 
   27 const TIME_ICON_BOD = 'hourglass-start';
   28 const TIME_ICON_MID = 'hourglass-half';
   29 const TIME_ICON_EOD = 'hourglass-end';
   30 
   31 const TIME_TYPES = [
   32   'hours',
   33   'minutes',
   34   'seconds',
   35   'milliseconds',
   36 ];
   37 
   38 const SetTimeOption = styled.div`
   39   display: flex;
   40   align-items: center;
   41   justify-content: center;
   42   flex: 1;
   43   padding-top: 12px;
   44 
   45   b { padding: 0 3px; }
   46 `;
   47 
   48 const StyledFormControl = styled(FormControl)`
   49   padding: 0 6px 0 9px;
   50 
   51   :nth-of-type(1) {
   52     grid-area: 2 / 2 / 2 / 2;
   53   }
   54   
   55   :nth-of-type(2) {
   56     grid-area: 2 / 4 / 2 / 4;
   57   }
   58   
   59   :nth-of-type(3) {
   60     grid-area: 2 / 6 / 2 / 6;
   61   }
   62 `;
   63 
   64 const StyledInputAddon = styled(InputGroup.Addon)(({ theme }) => css`
   65   padding: 0;
   66   background: ${theme.colors.variant.lightest.default};
   67   font-weight: bold;
   68   width: auto;
   69   display: flex;
   70   align-items: center;
   71 
   72   &:not(:first-child):not(:last-child) {
   73     border-right: 0;
   74     border-left: 0;
   75     padding: 0 3px;
   76   }
   77 
   78   :nth-of-type(1) {
   79     grid-area: 2 / 1 / 2 / 1;
   80   }
   81   
   82   :nth-of-type(2) {
   83     grid-area: 2 / 3 / 2 / 3;
   84   }
   85   
   86   :nth-of-type(3) {
   87     grid-area: 2 / 5 / 2 / 5;
   88   }
   89   
   90   :nth-of-type(4) {
   91     grid-area: 2 / 7 / 2 / 7;
   92   }
   93 `);
   94 
   95 const StyledButton = styled(Button)`
   96   padding: 6px 9px;
   97   line-height: 1.1;
   98 `;
   99 
  100 const FormGroupGrid = styled(FormGroup)`
  101   display: grid;
  102   grid-template-columns: max-content repeat(3, 1fr max-content);
  103   grid-template-rows: auto 1fr;
  104 
  105   label {
  106     padding-left: 6px;
  107     margin: 0;
  108     
  109     :nth-child(1) {
  110       grid-area: 1 / 2 / 1 / 2;
  111     }
  112 
  113     :nth-child(2) {
  114       grid-area: 1 / 4 / 1 / 4;
  115     }
  116 
  117     :nth-child(3) {
  118       grid-area: 1 / 6 / 1 / 6;
  119     }
  120   }
  121 `;
  122 
  123 const GridInputGroup = styled(InputGroup)`
  124   display: contents;
  125 `;
  126 
  127 const _onFocusSelect = (event) => {
  128   event.target.select();
  129 };
  130 
  131 const zeroPad = (data, pad = 2) => String(data).padStart(pad, '0');
  132 
  133 const parseTimeValue = (value, type) => {
  134   const isNotNumeric = value.match(/[^0-9]/g);
  135 
  136   const timeValue = Number(isNotNumeric ? 0 : value);
  137 
  138   if (type === 'hours') {
  139     if (timeValue > 23) {
  140       return 23;
  141     }
  142   } else if (timeValue > 59) {
  143     return 59;
  144   }
  145 
  146   return timeValue;
  147 };
  148 
  149 const fieldUpdate = (value) => {
  150   const initialDateTime = moment(value).toObject();
  151 
  152   TIME_TYPES.forEach((type) => {
  153     initialDateTime[type] = zeroPad(initialDateTime[type]);
  154   });
  155 
  156   const handleChangeSetTime = (event) => {
  157     const timeType = event.target.getAttribute('id').split('-').pop();
  158     const timeValue = parseTimeValue(event.target.value, timeType);
  159 
  160     const newTime = moment({
  161       ...initialDateTime,
  162       [timeType]: timeValue,
  163     });
  164 
  165     return newTime.format(DateTime.Formats.DATETIME);
  166   };
  167 
  168   const handleClickTimeNow = () => {
  169     const newTime = DateTime.now().toObject();
  170 
  171     return moment({
  172       ...initialDateTime,
  173       hours: newTime.hours,
  174       minutes: newTime.minutes,
  175       seconds: newTime.seconds,
  176     }).format(DateTime.Formats.DATETIME);
  177   };
  178 
  179   const handleTimeToggle = (eod = false) => {
  180     return moment({
  181       ...initialDateTime,
  182       hours: eod ? 23 : 0,
  183       minutes: eod ? 59 : 0,
  184       seconds: eod ? 59 : 0,
  185     }).format(DateTime.Formats.DATETIME);
  186   };
  187 
  188   return {
  189     initialDateTime,
  190     handleChangeSetTime,
  191     handleClickTimeNow,
  192     handleTimeToggle,
  193   };
  194 };
  195 
  196 const AbsoluteTimeInput = ({ dateTime, range, onChange }) => {
  197   const hourIcon = useRef(TIME_ICON_MID);
  198 
  199   const {
  200     initialDateTime,
  201     handleChangeSetTime,
  202     handleClickTimeNow,
  203     handleTimeToggle,
  204   } = fieldUpdate(dateTime);
  205 
  206   const _onChangeSetTime = (event) => {
  207     hourIcon.current = TIME_ICON_MID;
  208 
  209     onChange(handleChangeSetTime(event));
  210   };
  211 
  212   const _onClickHourToggle = () => {
  213     const endOfDay = hourIcon.current === TIME_ICON_BOD;
  214 
  215     if (endOfDay) {
  216       hourIcon.current = TIME_ICON_EOD;
  217     } else {
  218       hourIcon.current = TIME_ICON_BOD;
  219     }
  220 
  221     onChange(handleTimeToggle(endOfDay));
  222   };
  223 
  224   const _onClickTimeNow = () => {
  225     hourIcon.current = TIME_ICON_MID;
  226 
  227     onChange(handleClickTimeNow());
  228   };
  229 
  230   return (
  231     <SetTimeOption>
  232       <FormGroupGrid>
  233         <label htmlFor={`${range}-time-hours`} title={`${range} hours label`}>HH</label>
  234         <label htmlFor={`${range}-time-minutes`} title={`${range} minutes label`}>mm</label>
  235         <label htmlFor={`${range}-time-seconds`} title={`${range} seconds label`}>ss</label>
  236         <GridInputGroup>
  237           <StyledInputAddon>
  238             <StyledButton bsStyle="link"
  239                           bsSize="small"
  240                           onClick={_onClickHourToggle}
  241                           title="Toggle between beginning and end of day">
  242               <Icon name={hourIcon.current} />
  243             </StyledButton>
  244           </StyledInputAddon>
  245           <StyledFormControl type="number"
  246                              id={`${range}-time-hours`}
  247                              title={`${range} hour`}
  248                              value={initialDateTime.hours ?? ''}
  249                              onChange={_onChangeSetTime}
  250                              onFocus={_onFocusSelect}
  251                              bsSize="sm" />
  252           <StyledInputAddon>:</StyledInputAddon>
  253           <StyledFormControl type="number"
  254                              id={`${range}-time-minutes`}
  255                              title={`${range} minutes`}
  256                              value={initialDateTime.minutes ?? ''}
  257                              onChange={_onChangeSetTime}
  258                              onFocus={_onFocusSelect}
  259                              bsSize="sm" />
  260           <StyledInputAddon>:</StyledInputAddon>
  261           <StyledFormControl type="number"
  262                              id={`${range}-time-seconds`}
  263                              title={`${range} seconds`}
  264                              value={initialDateTime.seconds ?? ''}
  265                              onChange={_onChangeSetTime}
  266                              onFocus={_onFocusSelect}
  267                              bsSize="sm" />
  268           <StyledInputAddon>
  269             <StyledButton bsStyle="link"
  270                           bsSize="small"
  271                           onClick={_onClickTimeNow}
  272                           title="Set to current local time">
  273               <Icon name="magic" />
  274             </StyledButton>
  275           </StyledInputAddon>
  276         </GridInputGroup>
  277       </FormGroupGrid>
  278     </SetTimeOption>
  279   );
  280 };
  281 
  282 AbsoluteTimeInput.propTypes = {
  283   dateTime: PropTypes.string.isRequired,
  284   range: PropTypes.string.isRequired,
  285   onChange: PropTypes.func,
  286 };
  287 
  288 AbsoluteTimeInput.defaultProps = {
  289   onChange: () => {},
  290 };
  291 
  292 export default AbsoluteTimeInput;