diff --git a/public/locales/fi/translation.json b/public/locales/fi/translation.json index 3e0852275..fdfa29328 100644 --- a/public/locales/fi/translation.json +++ b/public/locales/fi/translation.json @@ -101,7 +101,8 @@ "confirm-dates":"Vahvista päivämäärät", "dates-confirmed":"Päivämäärät on vahvistettu", "new-esillaolo":"Lisää uusi esilläolo", - "delete-esillaolo":"Poista esilläolo" + "delete-esillaolo":"Poista esilläolo", + "modify-timeline":"Muokkaa aikataulua" }, "common": { "cancel": "Peruuta", diff --git a/src/components/ProjectTimeline/TimelineModal.js b/src/components/ProjectTimeline/TimelineModal.js index 8d8c8e65d..f40d69ae5 100644 --- a/src/components/ProjectTimeline/TimelineModal.js +++ b/src/components/ProjectTimeline/TimelineModal.js @@ -1,6 +1,6 @@ import React from 'react' import { Modal } from 'semantic-ui-react' -import { Button, Accordion } from 'hds-react' +import { Button,Tabs } from 'hds-react' import { EDIT_PROJECT_TIMETABLE_FORM } from '../../constants' import { useTranslation } from 'react-i18next' import FormField from '../input/FormField' @@ -8,9 +8,7 @@ import { isArray } from 'lodash' import { showField } from '../../utils/projectVisibilityUtils' import './VisTimeline.css' -const TimelineModal = ({ open,group,deadlines,openDialog,attributeData,formValues,deadlineSections,formSubmitErrors,projectPhaseIndex,archived,allowedToEdit }) => { - console.log(attributeData,formValues) - console.log(deadlineSections,deadlines) +const TimelineModal = ({ open,group,content,deadlines,openDialog,attributeData,formValues,deadlineSections,formSubmitErrors,projectPhaseIndex,archived,allowedToEdit }) => { const { t } = useTranslation() const getFormField = (fieldProps, key, disabled) => { @@ -119,15 +117,25 @@ const TimelineModal = ({ open,group,deadlines,openDialog,attributeData,formValue return ( - {group} + + +
{deadlineSections.map((section, i) => { if (section.title === group) { return( - + + + {section.title} + + {renderSection(section, i)} - + + ) } })} diff --git a/src/components/ProjectTimeline/VisTimeline.js b/src/components/ProjectTimeline/VisTimeline.js index 5e067918a..8d50e65a4 100644 --- a/src/components/ProjectTimeline/VisTimeline.js +++ b/src/components/ProjectTimeline/VisTimeline.js @@ -39,7 +39,6 @@ function VisTimeline({deadlines}) { */ const move = (percentage) => { var range = timeline.getWindow(); - console.log(range) var interval = range.end - range.start; timeline.setWindow({ @@ -105,7 +104,6 @@ function VisTimeline({deadlines}) { if(!subtract){ let originalDiff = moment.duration(moment(timeData.end).diff(moment(timeData.start))) let originalTimeFrame = originalDiff.asDays() - //console.log(originalTimeFrame) timeData.start = item.end timeData.end = moment(timeData.start).add(originalTimeFrame, 'days').toDate() } @@ -125,7 +123,6 @@ function VisTimeline({deadlines}) { } const onRangeChanged = ({ start, end }) => { - console.log(start, end) const Min = 1000 * 60 * 60 * 24; // one day in milliseconds const Max = 31556952000; // 1000 * 60 * 60 * 24 * 365.25 one year in milliseconds let a0 = 10; @@ -138,18 +135,14 @@ function VisTimeline({deadlines}) { // Arithmatic progression variables if (mins !== 0) { const x = (mins - a0) / distance; // Arithmatic progression formula - console.log(x) if(x > 50){ - console.log("smaller then 50") document.querySelectorAll('.inner, .inner-end').forEach(el => el.classList.add('hiddenTimes')); } else if(x < 50 && document.querySelectorAll('.hiddenTimes')){ - console.log("bigger then 50") document.querySelectorAll('.inner, .inner-end').forEach(el => el.classList.remove('hiddenTimes')); } } else { if(!document.querySelectorAll('.hiddenTimes')){ - console.log("100") document.querySelectorAll('.inner, .inner-end').forEach(el => el.classList.add('hiddenTimes')); } } diff --git a/src/components/ProjectTimeline/VisTimeline.scss b/src/components/ProjectTimeline/VisTimeline.scss index e10bd92ca..2cc3ce4f2 100644 --- a/src/components/ProjectTimeline/VisTimeline.scss +++ b/src/components/ProjectTimeline/VisTimeline.scss @@ -1,30 +1,8 @@ @import '../common/colors'; -.color-tram{ - background-color: $color_tram !important; -} -.color-summer{ - background-color: $color-summer !important; -} -.color-metro{ - background-color: $color_metro !important; -} -.color-bus{ - background-color: $color_bus !important; - color:white; -} -.color-gold{ - background-color: $color_gold !important; -} -.color-fog{ - background-color: $color_fog !important; -} .vis{ margin-top: 100px; margin-bottom: 20px; - .vis-item{ - // pointer-events: none; - } .vis-drag-left{ pointer-events: auto; } @@ -39,29 +17,29 @@ justify-content: space-between; align-items: center; } -/* .rangeItem{ - pointer-events: auto; - position: relative; - z-index: 2000; - } */ .inner,.inner-end{ z-index: 1000; pointer-events: auto; - // top: 18px !important; + border-width: 0; .vis-item-overflow{ height: 5px; + border-top: 4px dotted rgba(0, 0, 0, .95); + color: #fff; + background-color: #fff; + width: 100%; .vis-item-content{ pointer-events: auto; padding:0; } } .vis-drag-left,.vis-drag-right{ - height: 7px !important; - width: 7px !important; - background-color: black; + height: 18px !important; + width: 18px !important; + background-color:#f2f2f2; border-radius: 50%; - top: -1px !important; + top: -8px !important; display: inline-block; + border: 1px solid black; } } @@ -73,11 +51,6 @@ padding-left: 10px; } - /* gray background in weekends, white text color */ - .vis-time-axis .vis-grid.vis-saturday, - .vis-time-axis .vis-grid.vis-sunday { - background: gray; - } .negative{ background-color: rgba(255, 0, 0, 0.2) !important; } @@ -90,6 +63,7 @@ border-top: none; border-left: none; border-right: none; + background: #ffffff !important; .vis-inner{ padding: 0; display: flex; @@ -147,63 +121,72 @@ } } } -} -.vis-boxes{ - margin-top: 100px; - margin-bottom: 20px; - .vis-item{ - // pointer-events: none; - } - .vis-drag-left{ - pointer-events: auto; - } - .vis-drag-right{ - pointer-events: auto; - } - .vis-time-axis.vis-foreground{ - background-color: $light-gray3; + .vis-label{ + background-color: #F2F2F2; } - .timeline-menu { + + .vis-nesting-group{ display: flex; - justify-content: space-between; + justify-content: flex-start; align-items: center; - } - - .vis-box{ - position: absolute; - z-index: 2000; - margin-top:-30px; + margin-right: -1px; } - .vis-dot{ - top: -30px; + .vis-label.vis-nesting-group.expanded:before { + content: ""; + width: 18px; + height: 100%; + background: url('../../assets/icons/angle-up.svg') no-repeat; + background-position-x: center; + background-position-y: center; + background-size: 18px; } - .vis-line{ - z-index: 2001; - height: 50px !important; + .vis-label.vis-nesting-group.collapsed:before{ + content: ""; + width: 18px; + height: 100%; + background: url('../../assets/icons/angle-down.svg') no-repeat; + background-position-x: center; + background-position-y: center; + background-size: 18px; } - .vis-ltr .vis-label.vis-nested-group .vis-inner { - padding-left: 10px; + .vis-minor{ + background-color: white; + border-left: 1px solid #b4b4b4; + border-top: 1px solid #b4b4b4; + border-bottom: 1px solid #b4b4b4; } - /* gray background in weekends, white text color */ .vis-time-axis .vis-grid.vis-saturday, .vis-time-axis .vis-grid.vis-sunday { - background: gray; + background: #F2F2F2; } - .negative{ - background-color: rgba(255, 0, 0, 0.2); + + .vis-saturday,.vis-sunday{ + background: #F2F2F2; } -} -.edit-timeline-button-container{ - display: flex; - margin-bottom: 80px; - justify-content: flex-end; - .edit-timeline-button{ - margin-left: 20px; + .color-tram{ + background-color: $color_tram !important; + } + .color-summer{ + background-color: $color-summer !important; + } + .color-metro{ + background-color: $color_metro !important; + } + .color-bus{ + background-color: $color_bus !important; + color:white; } + .color-gold{ + background-color: $color_gold !important; + } + .color-fog{ + background-color: $color_fog !important; + } + } \ No newline at end of file diff --git a/src/components/ProjectTimeline/VisTimelineBoxes.js b/src/components/ProjectTimeline/VisTimelineBoxes.js index 7d0393fd1..d55bcea91 100644 --- a/src/components/ProjectTimeline/VisTimelineBoxes.js +++ b/src/components/ProjectTimeline/VisTimelineBoxes.js @@ -125,7 +125,6 @@ function VisTimelineBoxes({deadlines}) { } const onRangeChanged = ({ start, end }) => { - console.log(start, end) const Min = 1000 * 60 * 60 * 24; // one day in milliseconds const Max = 31556952000; // 1000 * 60 * 60 * 24 * 365.25 one year in milliseconds let a0 = 10; @@ -138,18 +137,14 @@ function VisTimelineBoxes({deadlines}) { // Arithmatic progression variables if (mins !== 0) { const x = (mins - a0) / distance; // Arithmatic progression formula - console.log(x) if(x > 50){ - console.log("smaller then 50") document.querySelectorAll('.inner, .inner-end').forEach(el => el.classList.add('hiddenTimes')); } else if(x < 50 && document.querySelectorAll('.hiddenTimes')){ - console.log("bigger then 50") document.querySelectorAll('.inner, .inner-end').forEach(el => el.classList.remove('hiddenTimes')); } } else { if(!document.querySelectorAll('.hiddenTimes')){ - console.log("100") document.querySelectorAll('.inner, .inner-end').forEach(el => el.classList.add('hiddenTimes')); } } diff --git a/src/components/ProjectTimeline/VisTimelineGroup.js b/src/components/ProjectTimeline/VisTimelineGroup.js index c92940167..6d032b459 100644 --- a/src/components/ProjectTimeline/VisTimelineGroup.js +++ b/src/components/ProjectTimeline/VisTimelineGroup.js @@ -1,5 +1,6 @@ import React, {useRef, useEffect, useState} from 'react'; import Moment from 'moment' +import 'moment/locale/fi'; import {extendMoment} from 'moment-range' //import { createRoot } from 'react-dom/client' //import ItemRange from './ItemRange' @@ -9,7 +10,7 @@ import * as vis from 'vis-timeline' import * as visdata from 'vis-data' import 'vis-timeline/dist/vis-timeline-graph2d.min.css' import './VisTimeline.css' - +Moment().locale('fi'); /* const createRootForTimelineItem = ( item, element, @@ -60,6 +61,7 @@ function VisTimeline({attributeData, deadlines, formValues, deadlineSections, fo var currentYear = now.getFullYear(); var startOfYear = new Date(currentYear, 0, 1); var endOfYear = new Date(currentYear, 11, 31); + timeline.setOptions({timeAxis: {scale: 'month'}}); timeline.setWindow(startOfYear, endOfYear); } @@ -68,6 +70,7 @@ function VisTimeline({attributeData, deadlines, formValues, deadlineSections, fo var currentYear = now.getFullYear(); var startOfMonth = new Date(currentYear, now.getMonth(), 1); var endOfMonth = new Date(currentYear, now.getMonth() + 1, 0); + timeline.setOptions({timeAxis: {scale: 'weekday'}}); timeline.setWindow(startOfMonth, endOfMonth); } @@ -126,6 +129,120 @@ function VisTimeline({attributeData, deadlines, formValues, deadlineSections, fo setToggleTimelineModal({open:!toggleTimelineModal.open,content:data.content,group:data.nestedInGroup,id:data.id,abbreviation:data.abbreviation,locked:data.locked}) } + const getTimelineData = (deadlines) => { + const phaseData = [] + let deadLineGroups = [] + let nestedDeadlines = [] + + let startDate = false + let endDate = false + let dashStart = false + let dashEnd = false + let innerStart = false + let innerEnd = false + let numberOfPhases = 1 + let style = "" + let dashedStyle = "" + let innerStyle = "" + + for (let i = 0; i < deadlines.length; i++) { + if (!deadLineGroups.some(item => item.id === deadlines[i].deadline.phase_name)) { + deadLineGroups.push({ + id: deadlines[i].deadline.phase_name, + content: deadlines[i].deadline.phase_name, + showNested: true, + nestedGroups: deadlines[i].deadline.phase_name === "Käynnistys" ? false : [] + }); + } + + if(deadlines[i].deadline.deadline_types.includes('phase_start')){ + startDate = deadlines[i].date + style = deadlines[i].deadline.phase_color + //.setHours(23,59,59,0) + } + else if(deadlines[i].deadline.deadline_types.includes('dashed_start')){ + dashStart = deadlines[i].date + dashedStyle = "inner" + } + else if(deadlines[i].deadline.deadline_types.includes('dashed_end') || deadlines[i].deadline.deadline_types.includes('inner_start')){ + dashEnd = deadlines[i].date + innerStart = deadlines[i].date + } + else if(deadlines[i].deadline.deadline_types.includes('inner_end')){ + innerEnd = deadlines[i].date + innerStyle = "inner-end" + } + else if(deadlines[i].deadline.deadline_types.includes('phase_end') && deadlines[i].deadline.date_type !== "Arkipäivät"){ + endDate = deadlines[i].date + //new Date .setHours(0,0,0,0) + } + + if(startDate && endDate){ + phaseData.push({ + id: numberOfPhases, + content: '', + start:startDate, + end:endDate, + className:style, + phaseID:deadlines[i].deadline.phase_id, + phase:true, + group:deadlines[i].deadline.phase_name, + }) + startDate = false + endDate = false + numberOfPhases++ + } + else if(dashStart && dashEnd){ + phaseData.push({ + id: numberOfPhases, + content: "", + start:dashStart, + end:dashEnd, + className:dashedStyle, + title: deadlines[i].deadline.attribute, + phaseID:deadlines[i].deadline.phase_id, + phase:false, + group:numberOfPhases, + locked:false + }) + dashEnd = false + deadLineGroups.at(-1).nestedGroups.push(numberOfPhases) + nestedDeadlines.push({ + id: numberOfPhases, + content: "Määräaika", + abbreviation:deadlines[i].abbreviation, + locked:false + }); + numberOfPhases++ + } + else if(innerStart && innerEnd){ + phaseData.push({ + id: numberOfPhases, + content: "", + start:innerStart, + end:innerEnd, + className:innerStyle, + title: deadlines[i].deadline.attribute, + phaseID:deadlines[i].deadline.phase_id, + phase:false, + group:numberOfPhases, + locked:false + }) + innerEnd = false + deadLineGroups.at(-1).nestedGroups.push(numberOfPhases) + nestedDeadlines.push({ + id: numberOfPhases, + content: "Esilläolo", + abbreviation:deadlines[i].abbreviation, + locked:false + }); + numberOfPhases++ + } + } + + return [deadLineGroups,nestedDeadlines,phaseData] + } + const lockLine = (data) => { console.log(data) //setLock({group:data.nestedInGroup,id:data.id,abbreviation:data.abbreviation,locked:!data.locked}) @@ -165,10 +282,20 @@ function VisTimeline({attributeData, deadlines, formValues, deadlineSections, fo useEffect(() => { const options = { + locales: { + fi: { + current: "Nykyinen", + time: "Aika", + } + }, + locale: 'fi', stack: false, + selectable: false, multiselect: false, sequentialSelection: false, - groupHeightMode:"fitItems", + moveable:true, + zoomable:false, + groupHeightMode:"fixed", width: '100%', zoomMin: 1000 * 60 * 60 * 24, // one day in milliseconds zoomMax: 31556952000, // 1000 * 60 * 60 * 24 * 365.25 one year in milliseconds @@ -187,6 +314,9 @@ function VisTimeline({attributeData, deadlines, formValues, deadlineSections, fo item:true, range:true }, + orientation:{ + axis: "top", + }, format: { minorLabels: { millisecond:'SSS', @@ -344,115 +474,7 @@ function VisTimeline({attributeData, deadlines, formValues, deadlineSections, fo let items = new visdata.DataSet() let groups = new visdata.DataSet(); - let deadLineGroups = [] - let nestedDeadlines = [] - - const phaseData = [] - let startDate = false - let endDate = false - let dashStart = false - let dashEnd = false - let innerStart = false - let innerEnd = false - let numberOfPhases = 1 - let style = "" - let dashedStyle = "" - let innerStyle = "" - - for (let i = 0; i < deadlines.length; i++) { - if (!deadLineGroups.some(item => item.id === deadlines[i].deadline.phase_name)) { - deadLineGroups.push({ - id: deadlines[i].deadline.phase_name, - content: deadlines[i].deadline.phase_name, - showNested: false, - nestedGroups: [] - }); - } - - if(deadlines[i].deadline.deadline_types.includes('phase_start')){ - startDate = deadlines[i].date - style = deadlines[i].deadline.phase_color - //.setHours(23,59,59,0) - } - else if(deadlines[i].deadline.deadline_types.includes('dashed_start')){ - dashStart = deadlines[i].date - dashedStyle = "inner" - } - else if(deadlines[i].deadline.deadline_types.includes('dashed_end') || deadlines[i].deadline.deadline_types.includes('inner_start')){ - dashEnd = deadlines[i].date - innerStart = deadlines[i].date - } - else if(deadlines[i].deadline.deadline_types.includes('inner_end')){ - innerEnd = deadlines[i].date - innerStyle = "inner-end" - } - else if(deadlines[i].deadline.deadline_types.includes('phase_end') && deadlines[i].deadline.date_type !== "Arkipäivät"){ - endDate = deadlines[i].date - //new Date .setHours(0,0,0,0) - } - - if(startDate && endDate){ - phaseData.push({ - id: numberOfPhases, - content: '', - start:startDate, - end:endDate, - className:style, - phaseID:deadlines[i].deadline.phase_id, - phase:true, - group:deadlines[i].deadline.phase_name, - }) - startDate = false - endDate = false - numberOfPhases++ - } - else if(dashStart && dashEnd){ - phaseData.push({ - id: numberOfPhases, - content: "", - start:dashStart, - end:dashEnd, - className:dashedStyle, - title: deadlines[i].deadline.attribute, - phaseID:deadlines[i].deadline.phase_id, - phase:false, - group:numberOfPhases, - locked:false - }) - dashEnd = false - deadLineGroups.at(-1).nestedGroups.push(numberOfPhases) - nestedDeadlines.push({ - id: numberOfPhases, - content: "Määräaika", - abbreviation:deadlines[i].abbreviation, - locked:false - }); - numberOfPhases++ - } - else if(innerStart && innerEnd){ - phaseData.push({ - id: numberOfPhases, - content: "", - start:innerStart, - end:innerEnd, - className:innerStyle, - title: deadlines[i].deadline.attribute, - phaseID:deadlines[i].deadline.phase_id, - phase:false, - group:numberOfPhases, - locked:false - }) - innerEnd = false - deadLineGroups.at(-1).nestedGroups.push(numberOfPhases) - nestedDeadlines.push({ - id: numberOfPhases, - content: "Esilläolo", - abbreviation:deadlines[i].abbreviation, - locked:false - }); - numberOfPhases++ - } - } + let [deadLineGroups,nestedDeadlines,phaseData] = getTimelineData(deadlines) groups.add(deadLineGroups); groups.add(nestedDeadlines); @@ -472,6 +494,7 @@ function VisTimeline({attributeData, deadlines, formValues, deadlineSections, fo className: "negative", },] ) + const timeline = container.current && new vis.Timeline(container.current, items, options, groups); // add event listener diff --git a/src/components/ProjectTimeline/VisTimelineMenu.js b/src/components/ProjectTimeline/VisTimelineMenu.js index 3ad594d5f..fbf7b9114 100644 --- a/src/components/ProjectTimeline/VisTimelineMenu.js +++ b/src/components/ProjectTimeline/VisTimelineMenu.js @@ -1,21 +1,21 @@ import React from 'react' -import {Button,IconArrowLeft,IconArrowRight,IconZoomIn,IconZoomOut} from 'hds-react' +import {Button,IconArrowLeft,IconArrowRight,IconZoomIn} from 'hds-react' -function VisTimelineMenu({zoomIn, zoomOut, moveLeft, moveRight,showYers,showMonths,showWeeks,showDays}) { +function VisTimelineMenu({moveLeft, moveRight,showYers,showMonths}) { return (
- - - - + + + {/* + */}
- - - - + {/* + */} + + {/* */}
diff --git a/src/components/ProjectTimeline/VisTimelinesContainer.js b/src/components/ProjectTimeline/VisTimelinesContainer.js deleted file mode 100644 index 505bc14cf..000000000 --- a/src/components/ProjectTimeline/VisTimelinesContainer.js +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -//import VisTimeline from './VisTimeline'; -import VisTimelineGroup from './VisTimelineGroup'; -//import { Button } from 'hds-react' - -const VisTimelinesContainer = ({deadlines}) => { - // const [isTimeLineEditable, setIsTimeLineEditable] = useState(false); - -/* const toggleTimeLine = () => { - setIsTimeLineEditable(!isTimeLineEditable); - } */ - -/* const saveTimeline = () => { - alert("Tallennus toiminnallisuus ei ole vielä käytössä") - } */ - - return ( -
- -{/* {!isTimeLineEditable && } */} -
-{/* */} -{/* */} -
-
- ); -}; - -export default VisTimelinesContainer; \ No newline at end of file diff --git a/src/components/input/CustomCheckbox.js b/src/components/input/CustomCheckbox.js index 2fba7e79b..5a0bfbab3 100644 --- a/src/components/input/CustomCheckbox.js +++ b/src/components/input/CustomCheckbox.js @@ -61,11 +61,10 @@ const CustomCheckbox = ({ }, [value]) const onChangeSave = () => { - console.log(checked) setChecked( !checked ) onChange(!checked) } - console.log(autofillRule || disabled, name) + if(isProjectTimetableEdit){ return ( <> diff --git a/src/components/project/EditProjectTimetableModal/index.js b/src/components/project/EditProjectTimetableModal/index.js index 95815e74c..797db8976 100644 --- a/src/components/project/EditProjectTimetableModal/index.js +++ b/src/components/project/EditProjectTimetableModal/index.js @@ -10,7 +10,7 @@ import './styles.scss' import { deadlineSectionsSelector } from '../../../selectors/schemaSelector' import { withTranslation } from 'react-i18next' import { deadlinesSelector } from '../../../selectors/projectSelector' -import { Button } from 'hds-react' +import { Button,IconInfoCircle } from 'hds-react' import { isEqual } from 'lodash' import VisTimelineGroup from '../../ProjectTimeline/VisTimelineGroup' @@ -87,7 +87,7 @@ class EditProjectTimeTableModal extends Component { closeOnDimmerClick={false} className='modal-center-big' > - {t('deadlines.title')} + div{ - align-items: center; - justify-content: flex-start; - } - [role=heading] { - margin-right: 20px; - flex: 0; - } - } */ } button{ justify-content: flex-start;