taskjuggler 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +1 -1
- data/bin/tj3client +3 -0
- data/bin/tj3d +3 -0
- data/bin/tj3ts_receiver +3 -0
- data/bin/tj3ts_sender +3 -0
- data/bin/tj3ts_summary +3 -0
- data/data/css/tjmanual.css +14 -0
- data/data/css/tjreport.css +233 -21
- data/data/scripts/wz_tooltip.js +20 -20
- data/doc/AppConfig.html +1389 -0
- data/doc/Arguments.html +678 -0
- data/doc/COPYING.html +837 -0
- data/doc/Object.html +996 -0
- data/doc/README.html +523 -0
- data/doc/RuntimeConfig.html +762 -0
- data/doc/String.html +872 -0
- data/doc/TaskJuggler/Account.html +691 -0
- data/doc/TaskJuggler/AccountAttribute.html +707 -0
- data/doc/TaskJuggler/AccountScenario.html +650 -0
- data/doc/TaskJuggler/Allocation.html +898 -0
- data/doc/TaskJuggler/AllocationAttribute.html +737 -0
- data/doc/TaskJuggler/AttributeBase.html +1193 -0
- data/doc/TaskJuggler/AttributeDefinition.html +753 -0
- data/doc/TaskJuggler/BatchProcessor.html +1112 -0
- data/doc/TaskJuggler/Booking.html +797 -0
- data/doc/TaskJuggler/BookingListAttribute.html +709 -0
- data/doc/TaskJuggler/BooleanAttribute.html +707 -0
- data/doc/TaskJuggler/CSVFile.html +924 -0
- data/doc/TaskJuggler/CellSettingPattern.html +638 -0
- data/doc/TaskJuggler/CellSettingPatternList.html +687 -0
- data/doc/TaskJuggler/Charge.html +715 -0
- data/doc/TaskJuggler/ChargeListAttribute.html +671 -0
- data/doc/TaskJuggler/ChargeSet.html +887 -0
- data/doc/TaskJuggler/ChargeSetListAttribute.html +718 -0
- data/doc/TaskJuggler/ColumnListAttribute.html +673 -0
- data/doc/TaskJuggler/ColumnTable.html +701 -0
- data/doc/TaskJuggler/Daemon.html +728 -0
- data/doc/TaskJuggler/DateAttribute.html +675 -0
- data/doc/TaskJuggler/DefinitionListAttribute.html +593 -0
- data/doc/TaskJuggler/DependencyListAttribute.html +713 -0
- data/doc/TaskJuggler/DurationAttribute.html +707 -0
- data/doc/TaskJuggler/FixnumAttribute.html +629 -0
- data/doc/TaskJuggler/FlagListAttribute.html +709 -0
- data/doc/TaskJuggler/FloatAttribute.html +671 -0
- data/doc/TaskJuggler/FormatListAttribute.html +635 -0
- data/doc/TaskJuggler/GanttChart.html +1473 -0
- data/doc/TaskJuggler/GanttContainer.html +885 -0
- data/doc/TaskJuggler/GanttHeader.html +886 -0
- data/doc/TaskJuggler/GanttHeaderScaleItem.html +700 -0
- data/doc/TaskJuggler/GanttLine.html +1263 -0
- data/doc/TaskJuggler/GanttLoadStack.html +766 -0
- data/doc/TaskJuggler/GanttMilestone.html +865 -0
- data/doc/TaskJuggler/GanttRouter.html +1433 -0
- data/doc/TaskJuggler/GanttTaskBar.html +880 -0
- data/doc/TaskJuggler/HTMLDocument.html +719 -0
- data/doc/TaskJuggler/HTMLGraphics.html +775 -0
- data/doc/TaskJuggler/Interval.html +1016 -0
- data/doc/TaskJuggler/IntervalListAttribute.html +713 -0
- data/doc/TaskJuggler/JobInfo.html +881 -0
- data/doc/TaskJuggler/Journal.html +991 -0
- data/doc/TaskJuggler/JournalEntry.html +779 -0
- data/doc/TaskJuggler/JournalEntryList.html +952 -0
- data/doc/TaskJuggler/KeywordArray.html +628 -0
- data/doc/TaskJuggler/KeywordDocumentation.html +1662 -0
- data/doc/TaskJuggler/Limits/Limit.html +826 -0
- data/doc/TaskJuggler/Limits.html +966 -0
- data/doc/TaskJuggler/LimitsAttribute.html +707 -0
- data/doc/TaskJuggler/ListAttributeBase.html +641 -0
- data/doc/TaskJuggler/Log.html +1103 -0
- data/doc/TaskJuggler/LogFile.html +918 -0
- data/doc/TaskJuggler/LogicalAttribute.html +698 -0
- data/doc/TaskJuggler/LogicalExpression.html +739 -0
- data/doc/TaskJuggler/LogicalExpressionAttribute.html +629 -0
- data/doc/TaskJuggler/LogicalFlag.html +681 -0
- data/doc/TaskJuggler/LogicalFunction.html +1218 -0
- data/doc/TaskJuggler/LogicalOperation.html +1078 -0
- data/doc/TaskJuggler/Macro.html +646 -0
- data/doc/TaskJuggler/MacroParser.html +810 -0
- data/doc/TaskJuggler/MacroTable.html +810 -0
- data/doc/TaskJuggler/ManagerResponsibilities.html +674 -0
- data/doc/TaskJuggler/ManagerStatusRecord.html +678 -0
- data/doc/TaskJuggler/Message.html +757 -0
- data/doc/TaskJuggler/MessageHandler.html +679 -0
- data/doc/TaskJuggler/Navigator.html +867 -0
- data/doc/TaskJuggler/NavigatorElement.html +932 -0
- data/doc/TaskJuggler/NikuProject.html +662 -0
- data/doc/TaskJuggler/NikuReport.html +1316 -0
- data/doc/TaskJuggler/NikuResource.html +632 -0
- data/doc/TaskJuggler/OnShiftCache.html +864 -0
- data/doc/TaskJuggler/ProcessIntercom.html +847 -0
- data/doc/TaskJuggler/ProcessIntercomIface.html +664 -0
- data/doc/TaskJuggler/Project.html +3056 -0
- data/doc/TaskJuggler/ProjectBroker.html +1260 -0
- data/doc/TaskJuggler/ProjectBrokerIface.html +734 -0
- data/doc/TaskJuggler/ProjectFileParser.html +1951 -0
- data/doc/TaskJuggler/ProjectRecord.html +859 -0
- data/doc/TaskJuggler/ProjectServer.html +1092 -0
- data/doc/TaskJuggler/ProjectServerIface.html +768 -0
- data/doc/TaskJuggler/PropertyAttribute.html +629 -0
- data/doc/TaskJuggler/PropertyList.html +1336 -0
- data/doc/TaskJuggler/PropertySet.html +1785 -0
- data/doc/TaskJuggler/PropertyTreeNode.html +2482 -0
- data/doc/TaskJuggler/Query.html +1831 -0
- data/doc/TaskJuggler/RTFNavigator.html +729 -0
- data/doc/TaskJuggler/RTFQuery.html +1038 -0
- data/doc/TaskJuggler/RTFReport.html +740 -0
- data/doc/TaskJuggler/RealFormat.html +743 -0
- data/doc/TaskJuggler/RealFormatAttribute.html +593 -0
- data/doc/TaskJuggler/ReferenceAttribute.html +782 -0
- data/doc/TaskJuggler/Report.html +1255 -0
- data/doc/TaskJuggler/ReportBase.html +1198 -0
- data/doc/TaskJuggler/ReportContext.html +711 -0
- data/doc/TaskJuggler/ReportServer.html +988 -0
- data/doc/TaskJuggler/ReportServerIface.html +838 -0
- data/doc/TaskJuggler/ReportServerRecord.html +716 -0
- data/doc/TaskJuggler/ReportTable.html +1106 -0
- data/doc/TaskJuggler/ReportTableCell.html +1536 -0
- data/doc/TaskJuggler/ReportTableColumn.html +828 -0
- data/doc/TaskJuggler/ReportTableLegend.html +999 -0
- data/doc/TaskJuggler/ReportTableLine.html +1003 -0
- data/doc/TaskJuggler/Resource.html +938 -0
- data/doc/TaskJuggler/ResourceListAttribute.html +752 -0
- data/doc/TaskJuggler/ResourceListRE.html +674 -0
- data/doc/TaskJuggler/ResourceScenario.html +2457 -0
- data/doc/TaskJuggler/RichText.html +791 -0
- data/doc/TaskJuggler/RichTextAttribute.html +743 -0
- data/doc/TaskJuggler/RichTextDocument.html +972 -0
- data/doc/TaskJuggler/RichTextElement.html +1615 -0
- data/doc/TaskJuggler/RichTextException.html +667 -0
- data/doc/TaskJuggler/RichTextFunctionExample.html +737 -0
- data/doc/TaskJuggler/RichTextFunctionHandler.html +689 -0
- data/doc/TaskJuggler/RichTextImage.html +650 -0
- data/doc/TaskJuggler/RichTextIntermediate.html +1161 -0
- data/doc/TaskJuggler/RichTextParser.html +756 -0
- data/doc/TaskJuggler/RichTextScanner.html +2010 -0
- data/doc/TaskJuggler/RichTextSnip.html +942 -0
- data/doc/TaskJuggler/RichTextSyntaxRules.html +1722 -0
- data/doc/TaskJuggler/Scenario.html +594 -0
- data/doc/TaskJuggler/ScenarioData.html +815 -0
- data/doc/TaskJuggler/ScenarioListAttribute.html +671 -0
- data/doc/TaskJuggler/Scoreboard.html +1114 -0
- data/doc/TaskJuggler/SheetHandlerBase.html +1115 -0
- data/doc/TaskJuggler/SheetReceiver.html +1293 -0
- data/doc/TaskJuggler/SheetSender.html +1089 -0
- data/doc/TaskJuggler/Shift.html +689 -0
- data/doc/TaskJuggler/ShiftAssignment.html +950 -0
- data/doc/TaskJuggler/ShiftAssignments.html +1379 -0
- data/doc/TaskJuggler/ShiftAssignmentsAttribute.html +707 -0
- data/doc/TaskJuggler/ShiftScenario.html +720 -0
- data/doc/TaskJuggler/SortListAttribute.html +631 -0
- data/doc/TaskJuggler/SourceFileInfo.html +698 -0
- data/doc/TaskJuggler/StatusSheetReceiver.html +615 -0
- data/doc/TaskJuggler/StatusSheetReport.html +872 -0
- data/doc/TaskJuggler/StatusSheetSender.html +654 -0
- data/doc/TaskJuggler/StringAttribute.html +671 -0
- data/doc/TaskJuggler/SymbolAttribute.html +629 -0
- data/doc/TaskJuggler/SyntaxReference.html +1155 -0
- data/doc/TaskJuggler/TOCEntry.html +723 -0
- data/doc/TaskJuggler/TSResourceRecord.html +670 -0
- data/doc/TaskJuggler/TSTaskRecord.html +682 -0
- data/doc/TaskJuggler/TableColumnDefinition.html +830 -0
- data/doc/TaskJuggler/TableOfContents.html +692 -0
- data/doc/TaskJuggler/TableReport.html +2444 -0
- data/doc/TaskJuggler/Task.html +781 -0
- data/doc/TaskJuggler/TaskDependency.html +730 -0
- data/doc/TaskJuggler/TaskListAttribute.html +713 -0
- data/doc/TaskJuggler/TaskListRE.html +673 -0
- data/doc/TaskJuggler/TaskScenario.html +4380 -0
- data/doc/TaskJuggler/TextFormatter.html +911 -0
- data/doc/TaskJuggler/TextParser/Pattern.html +1482 -0
- data/doc/TaskJuggler/TextParser/Rule.html +1288 -0
- data/doc/TaskJuggler/TextParser/StackElement.html +726 -0
- data/doc/TaskJuggler/TextParser/TextParserResultArray.html +648 -0
- data/doc/TaskJuggler/TextParser/TokenDoc.html +680 -0
- data/doc/TaskJuggler/TextParser.html +1670 -0
- data/doc/TaskJuggler/TextReport.html +856 -0
- data/doc/TaskJuggler/TextScanner/BufferStreamHandle.html +831 -0
- data/doc/TaskJuggler/TextScanner/FileStreamHandle.html +832 -0
- data/doc/TaskJuggler/TextScanner/StreamHandle.html +737 -0
- data/doc/TaskJuggler/TextScanner.html +2430 -0
- data/doc/TaskJuggler/TimeSheet.html +1233 -0
- data/doc/TaskJuggler/TimeSheetReceiver.html +612 -0
- data/doc/TaskJuggler/TimeSheetRecord.html +1352 -0
- data/doc/TaskJuggler/TimeSheetReport.html +948 -0
- data/doc/TaskJuggler/TimeSheetSender.html +637 -0
- data/doc/TaskJuggler/TimeSheetSummary.html +865 -0
- data/doc/TaskJuggler/TimeSheets.html +674 -0
- data/doc/TaskJuggler/Tj3AppBase.html +782 -0
- data/doc/TaskJuggler/Tj3Client.html +1455 -0
- data/doc/TaskJuggler/Tj3Daemon.html +767 -0
- data/doc/TaskJuggler/Tj3SheetAppBase.html +696 -0
- data/doc/TaskJuggler/Tj3SsReceiver.html +682 -0
- data/doc/TaskJuggler/Tj3SsSender.html +708 -0
- data/doc/TaskJuggler/Tj3TsReceiver.html +681 -0
- data/doc/TaskJuggler/Tj3TsSender.html +702 -0
- data/doc/TaskJuggler/Tj3TsSummary.html +710 -0
- data/doc/TaskJuggler/TjException.html +630 -0
- data/doc/TaskJuggler/TjTime.html +2590 -0
- data/doc/TaskJuggler/TjpExample.html +835 -0
- data/doc/TaskJuggler/TjpExportRE.html +1581 -0
- data/doc/TaskJuggler/TjpSyntaxRules.html +13004 -0
- data/doc/TaskJuggler/UserManual.html +1145 -0
- data/doc/TaskJuggler/WorkingHours.html +1101 -0
- data/doc/TaskJuggler/WorkingHoursAttribute.html +694 -0
- data/doc/TaskJuggler/XMLBlob.html +645 -0
- data/doc/TaskJuggler/XMLComment.html +640 -0
- data/doc/TaskJuggler/XMLDocument.html +732 -0
- data/doc/TaskJuggler/XMLElement.html +900 -0
- data/doc/TaskJuggler/XMLNamedText.html +601 -0
- data/doc/TaskJuggler/XMLText.html +655 -0
- data/doc/TaskJuggler.html +2243 -0
- data/doc/index.html +3778 -17
- data/doc/lib/AccountScenario_rb.html +67 -0
- data/doc/lib/Account_rb.html +69 -0
- data/doc/lib/Allocation_rb.html +69 -0
- data/doc/lib/AppConfig_rb.html +69 -0
- data/doc/lib/AttributeBase_rb.html +67 -0
- data/doc/lib/AttributeDefinition_rb.html +65 -0
- data/doc/lib/Attributes_rb.html +81 -0
- data/doc/lib/BatchProcessor_rb.html +69 -0
- data/doc/lib/Booking_rb.html +65 -0
- data/doc/lib/ChargeSet_rb.html +67 -0
- data/doc/lib/Charge_rb.html +67 -0
- data/doc/lib/HTMLDocument_rb.html +67 -0
- data/doc/lib/Interval_rb.html +67 -0
- data/doc/lib/Journal_rb.html +65 -0
- data/doc/lib/KeywordArray_rb.html +65 -0
- data/doc/lib/KeywordDocumentation_rb.html +75 -0
- data/doc/lib/Limits_rb.html +67 -0
- data/doc/lib/LogFile_rb.html +67 -0
- data/doc/lib/Log_rb.html +69 -0
- data/doc/lib/LogicalExpression_rb.html +71 -0
- data/doc/lib/LogicalFunction_rb.html +67 -0
- data/doc/lib/LogicalOperation_rb.html +67 -0
- data/doc/lib/MacroParser_rb.html +69 -0
- data/doc/lib/MacroTable_rb.html +73 -0
- data/doc/lib/MessageHandler_rb.html +65 -0
- data/doc/lib/Message_rb.html +67 -0
- data/doc/lib/ProjectFileParser_rb.html +79 -0
- data/doc/lib/Project_rb.html +109 -0
- data/doc/lib/PropertyList_rb.html +65 -0
- data/doc/lib/PropertySet_rb.html +69 -0
- data/doc/lib/PropertyTreeNode_rb.html +65 -0
- data/doc/lib/Query_rb.html +67 -0
- data/doc/lib/RTFNavigator_rb.html +71 -0
- data/doc/lib/RTFQuery_rb.html +71 -0
- data/doc/lib/RTFReport_rb.html +69 -0
- data/doc/lib/RealFormat_rb.html +65 -0
- data/doc/lib/ResourceScenario_rb.html +67 -0
- data/doc/lib/Resource_rb.html +69 -0
- data/doc/lib/RichTextDocument_rb.html +71 -0
- data/doc/lib/RichTextElement_rb.html +73 -0
- data/doc/lib/RichTextFunctionExample_rb.html +71 -0
- data/doc/lib/RichTextFunctionHandler_rb.html +65 -0
- data/doc/lib/RichTextParser_rb.html +71 -0
- data/doc/lib/RichTextScanner_rb.html +67 -0
- data/doc/lib/RichTextSnip_rb.html +69 -0
- data/doc/lib/RichTextSyntaxRules_rb.html +65 -0
- data/doc/lib/RichText_rb.html +69 -0
- data/doc/lib/RuntimeConfig_rb.html +67 -0
- data/doc/lib/ScenarioData_rb.html +69 -0
- data/doc/lib/Scenario_rb.html +67 -0
- data/doc/lib/Scoreboard_rb.html +65 -0
- data/doc/lib/SheetHandlerBase_rb.html +69 -0
- data/doc/lib/SheetReceiver_rb.html +75 -0
- data/doc/lib/SheetSender_rb.html +73 -0
- data/doc/lib/ShiftAssignments_rb.html +67 -0
- data/doc/lib/ShiftScenario_rb.html +67 -0
- data/doc/lib/Shift_rb.html +69 -0
- data/doc/lib/SourceFileInfo_rb.html +65 -0
- data/doc/lib/StatusSheetReceiver_rb.html +67 -0
- data/doc/lib/StatusSheetSender_rb.html +67 -0
- data/doc/lib/SyntaxReference_rb.html +73 -0
- data/doc/lib/TOCEntry_rb.html +69 -0
- data/doc/lib/TableColumnDefinition_rb.html +65 -0
- data/doc/lib/TableOfContents_rb.html +69 -0
- data/doc/lib/TaskDependency_rb.html +65 -0
- data/doc/lib/TaskJuggler_rb.html +73 -0
- data/doc/lib/TaskScenario_rb.html +67 -0
- data/doc/lib/Task_rb.html +69 -0
- data/doc/lib/TextFormatter_rb.html +67 -0
- data/doc/lib/TextParser/Pattern_rb.html +67 -0
- data/doc/lib/TextParser/Rule_rb.html +65 -0
- data/doc/lib/TextParser/StackElement_rb.html +65 -0
- data/doc/lib/TextParser/TokenDoc_rb.html +65 -0
- data/doc/lib/TextParser_rb.html +75 -0
- data/doc/lib/TextScanner_rb.html +79 -0
- data/doc/lib/TimeSheetReceiver_rb.html +67 -0
- data/doc/lib/TimeSheetSender_rb.html +67 -0
- data/doc/lib/TimeSheetSummary_rb.html +67 -0
- data/doc/lib/TimeSheets_rb.html +65 -0
- data/doc/lib/Tj3AppBase_rb.html +77 -0
- data/doc/lib/Tj3Config_rb.html +69 -0
- data/doc/lib/Tj3SheetAppBase_rb.html +67 -0
- data/doc/lib/TjException_rb.html +65 -0
- data/doc/lib/TjTime_rb.html +69 -0
- data/doc/lib/TjpExample_rb.html +67 -0
- data/doc/lib/TjpSyntaxRules_rb.html +65 -0
- data/doc/lib/UTF8String_rb.html +65 -0
- data/doc/lib/UserManual_rb.html +77 -0
- data/doc/lib/WorkingHours_rb.html +67 -0
- data/doc/lib/XMLDocument_rb.html +67 -0
- data/doc/lib/XMLElement_rb.html +67 -0
- data/doc/lib/daemon/Daemon_rb.html +67 -0
- data/doc/lib/daemon/ProcessIntercom_rb.html +67 -0
- data/doc/lib/daemon/ProjectBroker_rb.html +79 -0
- data/doc/lib/daemon/ProjectServer_rb.html +83 -0
- data/doc/lib/daemon/ReportServer_rb.html +73 -0
- data/doc/lib/deep_copy_rb.html +65 -0
- data/doc/lib/reports/CSVFile_rb.html +67 -0
- data/doc/lib/reports/ColumnTable_rb.html +67 -0
- data/doc/lib/reports/GanttChart_rb.html +73 -0
- data/doc/lib/reports/GanttContainer_rb.html +67 -0
- data/doc/lib/reports/GanttHeaderScaleItem_rb.html +65 -0
- data/doc/lib/reports/GanttHeader_rb.html +67 -0
- data/doc/lib/reports/GanttLine_rb.html +77 -0
- data/doc/lib/reports/GanttLoadStack_rb.html +67 -0
- data/doc/lib/reports/GanttMilestone_rb.html +67 -0
- data/doc/lib/reports/GanttRouter_rb.html +65 -0
- data/doc/lib/reports/GanttTaskBar_rb.html +67 -0
- data/doc/lib/reports/HTMLGraphics_rb.html +65 -0
- data/doc/lib/reports/Navigator_rb.html +67 -0
- data/doc/lib/reports/NikuReport_rb.html +69 -0
- data/doc/lib/reports/ReportBase_rb.html +65 -0
- data/doc/lib/reports/ReportContext_rb.html +65 -0
- data/doc/lib/reports/ReportTableCell_rb.html +65 -0
- data/doc/lib/reports/ReportTableColumn_rb.html +65 -0
- data/doc/lib/reports/ReportTableLegend_rb.html +65 -0
- data/doc/lib/reports/ReportTableLine_rb.html +67 -0
- data/doc/lib/reports/ReportTable_rb.html +69 -0
- data/doc/lib/reports/Report_rb.html +91 -0
- data/doc/lib/reports/ResourceListRE_rb.html +73 -0
- data/doc/lib/reports/StatusSheetReport_rb.html +67 -0
- data/doc/lib/reports/TableReport_rb.html +75 -0
- data/doc/lib/reports/TaskListRE_rb.html +73 -0
- data/doc/lib/reports/TextReport_rb.html +67 -0
- data/doc/lib/reports/TimeSheetReport_rb.html +67 -0
- data/doc/lib/reports/TjpExportRE_rb.html +67 -0
- data/doc/lib/ruby-signal-bug_rb.html +54 -0
- data/doc/lib/taskjuggler3_rb.html +73 -0
- data/doc/lib/tj3client_rb.html +73 -0
- data/doc/lib/tj3d_rb.html +73 -0
- data/doc/lib/tj3man_rb.html +73 -0
- data/doc/lib/tj3ss_receiver_rb.html +69 -0
- data/doc/lib/tj3ss_sender_rb.html +69 -0
- data/doc/lib/tj3ts_receiver_rb.html +69 -0
- data/doc/lib/tj3ts_sender_rb.html +69 -0
- data/doc/lib/tj3ts_summary_rb.html +69 -0
- data/doc/rdoc.css +701 -0
- data/examples/tutorial.tjp +25 -6
- data/lib/Attributes.rb +6 -2
- data/lib/HTMLDocument.rb +18 -2
- data/lib/Journal.rb +47 -4
- data/lib/KeywordArray.rb +1 -1
- data/lib/KeywordDocumentation.rb +17 -77
- data/lib/Log.rb +3 -1
- data/lib/LogFile.rb +72 -0
- data/lib/LogicalExpression.rb +5 -10
- data/lib/LogicalFunction.rb +34 -18
- data/lib/LogicalOperation.rb +32 -18
- data/lib/Project.rb +85 -13
- data/lib/ProjectFileParser.rb +19 -6
- data/lib/PropertyList.rb +12 -2
- data/lib/PropertyTreeNode.rb +23 -9
- data/lib/Query.rb +51 -13
- data/lib/RTFReport.rb +2 -2
- data/lib/Resource.rb +157 -0
- data/lib/ResourceScenario.rb +215 -68
- data/lib/RichText.rb +15 -3
- data/lib/RichTextDocument.rb +2 -4
- data/lib/RichTextElement.rb +87 -25
- data/lib/RichTextScanner.rb +32 -5
- data/lib/RichTextSnip.rb +6 -4
- data/lib/RichTextSyntaxRules.rb +44 -8
- data/lib/RuntimeConfig.rb +93 -0
- data/lib/Scoreboard.rb +6 -6
- data/lib/SheetHandlerBase.rb +215 -0
- data/lib/SheetReceiver.rb +355 -0
- data/lib/SheetSender.rb +264 -0
- data/lib/ShiftAssignments.rb +35 -27
- data/lib/StatusSheetReceiver.rb +45 -0
- data/lib/StatusSheetSender.rb +54 -0
- data/lib/SyntaxReference.rb +2 -7
- data/lib/Task.rb +70 -0
- data/lib/TaskJuggler.rb +114 -12
- data/lib/TaskScenario.rb +131 -22
- data/lib/TextFormatter.rb +177 -0
- data/lib/TextParser.rb +10 -1
- data/lib/TextScanner.rb +63 -33
- data/lib/TimeSheetReceiver.rb +42 -0
- data/lib/TimeSheetSender.rb +55 -0
- data/lib/TimeSheetSummary.rb +149 -0
- data/lib/TimeSheets.rb +406 -0
- data/lib/Tj3AppBase.rb +114 -0
- data/lib/Tj3Config.rb +1 -1
- data/lib/Tj3SheetAppBase.rb +59 -0
- data/lib/TjTime.rb +14 -1
- data/lib/TjpSyntaxRules.rb +573 -211
- data/lib/UTF8String.rb +4 -0
- data/lib/UserManual.rb +8 -7
- data/lib/XMLElement.rb +27 -19
- data/lib/daemon/Daemon.rb +70 -0
- data/lib/daemon/ProcessIntercom.rb +117 -0
- data/lib/daemon/ProjectBroker.rb +450 -0
- data/lib/daemon/ProjectServer.rb +348 -0
- data/lib/daemon/ReportServer.rb +194 -0
- data/lib/reports/ColumnTable.rb +2 -0
- data/lib/reports/GanttChart.rb +5 -7
- data/lib/reports/GanttContainer.rb +5 -8
- data/lib/reports/GanttHeader.rb +1 -1
- data/lib/reports/GanttLine.rb +89 -53
- data/lib/reports/GanttMilestone.rb +7 -4
- data/lib/reports/GanttTaskBar.rb +7 -3
- data/lib/reports/HTMLGraphics.rb +24 -9
- data/lib/reports/NikuReport.rb +414 -0
- data/lib/reports/Report.rb +54 -20
- data/lib/reports/ReportBase.rb +21 -0
- data/lib/reports/ReportTable.rb +29 -11
- data/lib/reports/ReportTableCell.rb +154 -86
- data/lib/reports/ReportTableLegend.rb +77 -80
- data/lib/reports/ResourceListRE.rb +2 -3
- data/lib/reports/StatusSheetReport.rb +231 -0
- data/lib/reports/TableReport.rb +74 -65
- data/lib/reports/TaskListRE.rb +2 -4
- data/lib/reports/TextReport.rb +18 -12
- data/lib/reports/TimeSheetReport.rb +145 -80
- data/lib/reports/TjpExportRE.rb +4 -4
- data/lib/ruby-signal-bug.rb +43 -0
- data/lib/taskjuggler3.rb +27 -10
- data/lib/tj3client.rb +411 -77
- data/lib/tj3d.rb +110 -0
- data/lib/tj3ss_receiver.rb +56 -0
- data/lib/tj3ss_sender.rb +84 -0
- data/lib/tj3ts_receiver.rb +59 -0
- data/lib/tj3ts_sender.rb +78 -0
- data/lib/tj3ts_summary.rb +87 -0
- data/manual/Day_To_Day_Juggling +761 -32
- data/manual/Getting_Started +12 -12
- data/manual/Rich_Text_Attributes +13 -1
- data/manual/TaskJuggler_2x_Migration +41 -3
- data/manual/TaskJuggler_Internals +87 -0
- data/manual/The_TaskJuggler_Syntax +1 -2
- data/manual/Tutorial +10 -10
- data/test/TestSuite/CSV-Reports/celltext.tjp +1 -1
- data/test/TestSuite/HTML-Reports/TimeSheet.html +79 -0
- data/test/TestSuite/HTML-Reports/icons/trend-down.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/trend-flat.png +0 -0
- data/test/TestSuite/HTML-Reports/icons/trend-up.png +0 -0
- data/test/TestSuite/HTML-Reports/reference.html +51 -0
- data/test/TestSuite/Scheduler/Correct/Booking2.html +603 -0
- data/test/TestSuite/Scheduler/Correct/Booking2.tjp +57 -0
- data/test/TestSuite/Scheduler/Correct/Duration.tjp +32 -18
- data/test/TestSuite/Scheduler/Correct/Manager.tjp +9 -0
- data/test/TestSuite/Scheduler/Correct/Shift.html +429 -0
- data/test/TestSuite/Scheduler/Correct/Shift2.html +162 -0
- data/test/TestSuite/Scheduler/Correct/Shift2.tjp +67 -0
- data/test/TestSuite/{Syntax/Correct/TimeSheet.tjp → Scheduler/Correct/TimeSheet2.tjp} +21 -8
- data/test/TestSuite/Scheduler/Correct/css/tjmanual.css +52 -0
- data/test/TestSuite/Scheduler/Correct/css/tjreport.css +195 -0
- data/test/TestSuite/{Syntax → Scheduler}/Correct/icons/details.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/flag-green.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/flag-red.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/flag-yellow.png +0 -0
- data/test/TestSuite/{Syntax → Scheduler}/Correct/icons/resource.png +0 -0
- data/test/TestSuite/{Syntax → Scheduler}/Correct/icons/resourcegroup.png +0 -0
- data/test/TestSuite/{Syntax → Scheduler}/Correct/icons/task.png +0 -0
- data/test/TestSuite/{Syntax → Scheduler}/Correct/icons/taskgroup.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/trend-down.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/trend-flat.png +0 -0
- data/test/TestSuite/Scheduler/Correct/icons/trend-up.png +0 -0
- data/test/TestSuite/{HTML-Reports/scripts → Scheduler/Correct}/scripts/wz_tooltip.js +0 -0
- data/test/TestSuite/Scheduler/Errors/manager_is_group.tjp +15 -0
- data/test/TestSuite/Scheduler/Errors/manager_is_self.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/resource_fail_check.tjp +12 -0
- data/test/TestSuite/Scheduler/Errors/resource_warn_check.tjp +12 -0
- data/test/TestSuite/Scheduler/Errors/task_fail_check.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/task_warn_check.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/ts_alert1_more_details.tjp +20 -0
- data/test/TestSuite/Scheduler/Errors/ts_alert2_more_details.tjp +21 -0
- data/test/TestSuite/Scheduler/Errors/ts_no_expected_end.tjp +26 -0
- data/test/TestSuite/Scheduler/Errors/ts_no_headline1.tjp +27 -0
- data/test/TestSuite/Scheduler/Errors/ts_no_rem_or_end.tjp +26 -0
- data/test/TestSuite/Scheduler/Errors/ts_no_remaining.tjp +26 -0
- data/test/TestSuite/Scheduler/Errors/ts_no_status_work.tjp +18 -0
- data/test/TestSuite/Scheduler/Errors/ts_no_work.tjp +26 -0
- data/test/TestSuite/Scheduler/Errors/ts_res_new_task.tjp +20 -0
- data/test/TestSuite/Scheduler/Errors/ts_work_too_high.tjp +27 -0
- data/test/TestSuite/Scheduler/Errors/ts_work_too_low.tjp +27 -0
- data/test/TestSuite/StatusSheets/boss.tji +45 -0
- data/test/TestSuite/StatusSheets/boss_mail +51 -0
- data/test/TestSuite/StatusSheets/dev2_mail +37 -0
- data/test/TestSuite/StatusSheets/project.tjp +275 -0
- data/test/TestSuite/StatusSheets/run +50 -0
- data/test/TestSuite/Syntax/Correct/Include.tjp +4 -0
- data/test/TestSuite/Syntax/Correct/Limits-1.tjp +10 -1
- data/test/TestSuite/Syntax/Correct/Manager.tjp +30 -0
- data/test/TestSuite/Syntax/Correct/Niku.tjp +66 -0
- data/test/TestSuite/Syntax/Correct/TimeSheet1.tjp +83 -0
- data/test/TestSuite/Syntax/Correct/include/dir1/file2.tji +1 -0
- data/test/TestSuite/Syntax/Correct/include/dir2/file3.tji +2 -0
- data/test/TestSuite/Syntax/Correct/include/file1.tji +3 -0
- data/test/TestSuite/Syntax/Correct/tutorial.tjp +29 -8
- data/test/TestSuite/Syntax/Errors/ts_bad_priority.tjp +19 -0
- data/test/TestSuite/Syntax/Errors/ts_default_details.tjp +22 -0
- data/test/TestSuite/Syntax/Errors/ts_default_summary.tjp +22 -0
- data/test/TestSuite/Syntax/Errors/ts_duplicate_task.tjp +23 -0
- data/test/TestSuite/Syntax/Errors/ts_end_too_early.tjp +18 -0
- data/test/TestSuite/Syntax/Errors/ts_headline_too_long.tjp +19 -0
- data/test/TestSuite/Syntax/Errors/ts_no_headline2.tjp +27 -0
- data/test/TestSuite/Syntax/Errors/ts_summary_too_long.tjp +29 -0
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/boss_2002-03-01.tji +36 -0
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/dev1_2002-03-01.tji +48 -0
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/dev2_2002-03-01.tji +67 -0
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/dev3_2002-03-01.tji +67 -0
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/doc_2002-03-01.tji +48 -0
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/resources.yml +31 -0
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/2002-03-01/test_2002-03-01.tji +36 -0
- data/test/TestSuite/TimeSheets/TimeSheetTemplates/acceptable_intervals +1 -0
- data/test/TestSuite/TimeSheets/TimeSheets/2002-03-01/all.tji +1 -0
- data/test/TestSuite/TimeSheets/TimeSheets/2002-03-01/dev2_2002-03-01.tji +54 -0
- data/test/TestSuite/TimeSheets/TimeSheets/all.tji +2 -0
- data/test/TestSuite/TimeSheets/dev2_mail1 +84 -0
- data/test/TestSuite/TimeSheets/dev2_mail2 +87 -0
- data/test/TestSuite/TimeSheets/project.tjp +271 -0
- data/test/TestSuite/TimeSheets/receiver.log +102 -0
- data/test/TestSuite/TimeSheets/run +75 -0
- data/test/TestSuite/TimeSheets/sender.log +794 -0
- data/test/TestSuite/TimeSheets/summary.log +884 -0
- data/test/TestSuite/TimeSheets/timesheets.log +45 -0
- data/test/TestSuite/TimeSheets/tj3d.log +292 -0
- data/test/test_CSV-Reports.rb +5 -3
- data/test/test_RichText.rb +264 -56
- data/test/test_Scheduler.rb +1 -0
- data/test/test_TextFormatter.rb +142 -0
- data/test/test_TjTime.rb +15 -0
- metadata +816 -644
- data/benchmarks/UTF-8-Strings.rb +0 -58
- data/doc/classes/AppConfig.html +0 -880
- data/doc/classes/Arguments.html +0 -230
- data/doc/classes/Object.html +0 -229
- data/doc/classes/String.html +0 -399
- data/doc/classes/TaskJuggler/Account.html +0 -257
- data/doc/classes/TaskJuggler/AccountAttribute.html +0 -261
- data/doc/classes/TaskJuggler/AccountScenario.html +0 -218
- data/doc/classes/TaskJuggler/Allocation.html +0 -423
- data/doc/classes/TaskJuggler/AllocationAttribute.html +0 -291
- data/doc/classes/TaskJuggler/AttributeBase.html +0 -704
- data/doc/classes/TaskJuggler/AttributeDefinition.html +0 -276
- data/doc/classes/TaskJuggler/BatchProcessor.html +0 -347
- data/doc/classes/TaskJuggler/Booking.html +0 -311
- data/doc/classes/TaskJuggler/BookingListAttribute.html +0 -263
- data/doc/classes/TaskJuggler/BooleanAttribute.html +0 -261
- data/doc/classes/TaskJuggler/CSVFile.html +0 -329
- data/doc/classes/TaskJuggler/CellSettingPattern.html +0 -201
- data/doc/classes/TaskJuggler/CellSettingPatternList.html +0 -253
- data/doc/classes/TaskJuggler/Charge.html +0 -283
- data/doc/classes/TaskJuggler/ChargeListAttribute.html +0 -229
- data/doc/classes/TaskJuggler/ChargeSet.html +0 -444
- data/doc/classes/TaskJuggler/ChargeSetListAttribute.html +0 -276
- data/doc/classes/TaskJuggler/ColumnListAttribute.html +0 -231
- data/doc/classes/TaskJuggler/ColumnTable.html +0 -262
- data/doc/classes/TaskJuggler/DateAttribute.html +0 -233
- data/doc/classes/TaskJuggler/DefinitionListAttribute.html +0 -162
- data/doc/classes/TaskJuggler/DependencyListAttribute.html +0 -267
- data/doc/classes/TaskJuggler/DurationAttribute.html +0 -229
- data/doc/classes/TaskJuggler/FixnumAttribute.html +0 -194
- data/doc/classes/TaskJuggler/FlagListAttribute.html +0 -263
- data/doc/classes/TaskJuggler/FloatAttribute.html +0 -229
- data/doc/classes/TaskJuggler/FormatListAttribute.html +0 -197
- data/doc/classes/TaskJuggler/GanttChart.html +0 -696
- data/doc/classes/TaskJuggler/GanttContainer.html +0 -445
- data/doc/classes/TaskJuggler/GanttHeader.html +0 -284
- data/doc/classes/TaskJuggler/GanttHeaderScaleItem.html +0 -249
- data/doc/classes/TaskJuggler/GanttLine.html +0 -402
- data/doc/classes/TaskJuggler/GanttLoadStack.html +0 -331
- data/doc/classes/TaskJuggler/GanttMilestone.html +0 -419
- data/doc/classes/TaskJuggler/GanttRouter.html +0 -431
- data/doc/classes/TaskJuggler/GanttTaskBar.html +0 -433
- data/doc/classes/TaskJuggler/HTMLDocument.html +0 -240
- data/doc/classes/TaskJuggler/HTMLGraphics.html +0 -231
- data/doc/classes/TaskJuggler/Interval.html +0 -558
- data/doc/classes/TaskJuggler/IntervalListAttribute.html +0 -267
- data/doc/classes/TaskJuggler/JobInfo.html +0 -340
- data/doc/classes/TaskJuggler/Journal.html +0 -443
- data/doc/classes/TaskJuggler/JournalEntry.html +0 -274
- data/doc/classes/TaskJuggler/JournalEntryList.html +0 -454
- data/doc/classes/TaskJuggler/KeywordArray.html +0 -179
- data/doc/classes/TaskJuggler/KeywordDocumentation.html +0 -846
- data/doc/classes/TaskJuggler/Limits/Limit.html +0 -385
- data/doc/classes/TaskJuggler/Limits.html +0 -422
- data/doc/classes/TaskJuggler/LimitsAttribute.html +0 -261
- data/doc/classes/TaskJuggler/ListAttributeBase.html +0 -207
- data/doc/classes/TaskJuggler/Log.html +0 -655
- data/doc/classes/TaskJuggler/LogicalAttribute.html +0 -259
- data/doc/classes/TaskJuggler/LogicalExpression.html +0 -292
- data/doc/classes/TaskJuggler/LogicalExpressionAttribute.html +0 -194
- data/doc/classes/TaskJuggler/LogicalFlag.html +0 -209
- data/doc/classes/TaskJuggler/LogicalFunction.html +0 -339
- data/doc/classes/TaskJuggler/LogicalOperation.html +0 -351
- data/doc/classes/TaskJuggler/Macro.html +0 -198
- data/doc/classes/TaskJuggler/MacroParser.html +0 -360
- data/doc/classes/TaskJuggler/MacroTable.html +0 -370
- data/doc/classes/TaskJuggler/Message.html +0 -285
- data/doc/classes/TaskJuggler/MessageHandler.html +0 -231
- data/doc/classes/TaskJuggler/Navigator.html +0 -313
- data/doc/classes/TaskJuggler/NavigatorElement.html +0 -449
- data/doc/classes/TaskJuggler/OnShiftCache.html +0 -316
- data/doc/classes/TaskJuggler/Project.html +0 -2257
- data/doc/classes/TaskJuggler/ProjectFileParser.html +0 -420
- data/doc/classes/TaskJuggler/PropertyAttribute.html +0 -194
- data/doc/classes/TaskJuggler/PropertyList.html +0 -668
- data/doc/classes/TaskJuggler/PropertySet.html +0 -1286
- data/doc/classes/TaskJuggler/PropertyTreeNode.html +0 -1742
- data/doc/classes/TaskJuggler/Query.html +0 -870
- data/doc/classes/TaskJuggler/RTFNavigator.html +0 -293
- data/doc/classes/TaskJuggler/RTFQuery.html +0 -343
- data/doc/classes/TaskJuggler/RTFReport.html +0 -304
- data/doc/classes/TaskJuggler/RealFormat.html +0 -309
- data/doc/classes/TaskJuggler/RealFormatAttribute.html +0 -162
- data/doc/classes/TaskJuggler/ReferenceAttribute.html +0 -328
- data/doc/classes/TaskJuggler/RemoteServiceManager.html +0 -335
- data/doc/classes/TaskJuggler/Report.html +0 -321
- data/doc/classes/TaskJuggler/ReportBase.html +0 -437
- data/doc/classes/TaskJuggler/ReportContext.html +0 -248
- data/doc/classes/TaskJuggler/ReportServer.html +0 -320
- data/doc/classes/TaskJuggler/ReportTable.html +0 -526
- data/doc/classes/TaskJuggler/ReportTableCell.html +0 -614
- data/doc/classes/TaskJuggler/ReportTableColumn.html +0 -368
- data/doc/classes/TaskJuggler/ReportTableLegend.html +0 -347
- data/doc/classes/TaskJuggler/ReportTableLine.html +0 -481
- data/doc/classes/TaskJuggler/Resource.html +0 -211
- data/doc/classes/TaskJuggler/ResourceListAttribute.html +0 -302
- data/doc/classes/TaskJuggler/ResourceListRE.html +0 -245
- data/doc/classes/TaskJuggler/ResourceScenario.html +0 -1229
- data/doc/classes/TaskJuggler/RichText.html +0 -357
- data/doc/classes/TaskJuggler/RichTextAttribute.html +0 -293
- data/doc/classes/TaskJuggler/RichTextDocument.html +0 -424
- data/doc/classes/TaskJuggler/RichTextElement.html +0 -932
- data/doc/classes/TaskJuggler/RichTextException.html +0 -212
- data/doc/classes/TaskJuggler/RichTextFunctionExample.html +0 -301
- data/doc/classes/TaskJuggler/RichTextFunctionHandler.html +0 -245
- data/doc/classes/TaskJuggler/RichTextIntermediate.html +0 -563
- data/doc/classes/TaskJuggler/RichTextParser.html +0 -321
- data/doc/classes/TaskJuggler/RichTextScanner.html +0 -424
- data/doc/classes/TaskJuggler/RichTextSnip.html +0 -404
- data/doc/classes/TaskJuggler/RichTextSyntaxRules.html +0 -1105
- data/doc/classes/TaskJuggler/Scenario.html +0 -163
- data/doc/classes/TaskJuggler/ScenarioData.html +0 -358
- data/doc/classes/TaskJuggler/ScenarioListAttribute.html +0 -229
- data/doc/classes/TaskJuggler/Scoreboard.html +0 -642
- data/doc/classes/TaskJuggler/Shift.html +0 -255
- data/doc/classes/TaskJuggler/ShiftAssignment.html +0 -492
- data/doc/classes/TaskJuggler/ShiftAssignments.html +0 -719
- data/doc/classes/TaskJuggler/ShiftAssignmentsAttribute.html +0 -261
- data/doc/classes/TaskJuggler/ShiftScenario.html +0 -282
- data/doc/classes/TaskJuggler/SortListAttribute.html +0 -196
- data/doc/classes/TaskJuggler/SourceFileInfo.html +0 -251
- data/doc/classes/TaskJuggler/StringAttribute.html +0 -229
- data/doc/classes/TaskJuggler/SymbolAttribute.html +0 -194
- data/doc/classes/TaskJuggler/SyntaxReference.html +0 -520
- data/doc/classes/TaskJuggler/TOCEntry.html +0 -246
- data/doc/classes/TaskJuggler/TSResourceRecord.html +0 -197
- data/doc/classes/TaskJuggler/TSTaskRecord.html +0 -215
- data/doc/classes/TaskJuggler/TableColumnDefinition.html +0 -309
- data/doc/classes/TaskJuggler/TableOfContents.html +0 -260
- data/doc/classes/TaskJuggler/TableReport.html +0 -1015
- data/doc/classes/TaskJuggler/Task.html +0 -203
- data/doc/classes/TaskJuggler/TaskDependency.html +0 -255
- data/doc/classes/TaskJuggler/TaskListAttribute.html +0 -267
- data/doc/classes/TaskJuggler/TaskListRE.html +0 -245
- data/doc/classes/TaskJuggler/TaskScenario.html +0 -2543
- data/doc/classes/TaskJuggler/TextParser/Pattern.html +0 -927
- data/doc/classes/TaskJuggler/TextParser/Rule.html +0 -783
- data/doc/classes/TaskJuggler/TextParser/StackElement.html +0 -272
- data/doc/classes/TaskJuggler/TextParser/TextParserResultArray.html +0 -212
- data/doc/classes/TaskJuggler/TextParser/TokenDoc.html +0 -225
- data/doc/classes/TaskJuggler/TextParser.html +0 -754
- data/doc/classes/TaskJuggler/TextReport.html +0 -367
- data/doc/classes/TaskJuggler/TextScanner/BufferStreamHandle.html +0 -355
- data/doc/classes/TaskJuggler/TextScanner/FileStreamHandle.html +0 -348
- data/doc/classes/TaskJuggler/TextScanner/StreamHandle.html +0 -264
- data/doc/classes/TaskJuggler/TextScanner.html +0 -815
- data/doc/classes/TaskJuggler/TimeSheetReport.html +0 -406
- data/doc/classes/TaskJuggler/TjException.html +0 -185
- data/doc/classes/TaskJuggler/TjTime.html +0 -1904
- data/doc/classes/TaskJuggler/TjpExample.html +0 -314
- data/doc/classes/TaskJuggler/TjpExportRE.html +0 -306
- data/doc/classes/TaskJuggler/TjpSyntaxRules.html +0 -10812
- data/doc/classes/TaskJuggler/UserManual.html +0 -605
- data/doc/classes/TaskJuggler/WorkingHours.html +0 -586
- data/doc/classes/TaskJuggler/WorkingHoursAttribute.html +0 -252
- data/doc/classes/TaskJuggler/XMLBlob.html +0 -207
- data/doc/classes/TaskJuggler/XMLComment.html +0 -206
- data/doc/classes/TaskJuggler/XMLDocument.html +0 -298
- data/doc/classes/TaskJuggler/XMLElement.html +0 -389
- data/doc/classes/TaskJuggler/XMLNamedText.html +0 -174
- data/doc/classes/TaskJuggler/XMLText.html +0 -221
- data/doc/classes/TaskJuggler.html +0 -1573
- data/doc/files/COPYING.html +0 -448
- data/doc/files/README.html +0 -134
- data/doc/files/lib/AccountScenario_rb.html +0 -117
- data/doc/files/lib/Account_rb.html +0 -119
- data/doc/files/lib/Allocation_rb.html +0 -119
- data/doc/files/lib/AppConfig_rb.html +0 -119
- data/doc/files/lib/AttributeBase_rb.html +0 -117
- data/doc/files/lib/AttributeDefinition_rb.html +0 -107
- data/doc/files/lib/Attributes_rb.html +0 -131
- data/doc/files/lib/BatchProcessor_rb.html +0 -119
- data/doc/files/lib/Booking_rb.html +0 -107
- data/doc/files/lib/ChargeSet_rb.html +0 -117
- data/doc/files/lib/Charge_rb.html +0 -117
- data/doc/files/lib/HTMLDocument_rb.html +0 -117
- data/doc/files/lib/Interval_rb.html +0 -117
- data/doc/files/lib/Journal_rb.html +0 -107
- data/doc/files/lib/KeywordArray_rb.html +0 -107
- data/doc/files/lib/KeywordDocumentation_rb.html +0 -123
- data/doc/files/lib/Limits_rb.html +0 -117
- data/doc/files/lib/Log_rb.html +0 -117
- data/doc/files/lib/LogicalExpression_rb.html +0 -121
- data/doc/files/lib/LogicalFunction_rb.html +0 -117
- data/doc/files/lib/LogicalOperation_rb.html +0 -117
- data/doc/files/lib/MacroParser_rb.html +0 -119
- data/doc/files/lib/MacroTable_rb.html +0 -123
- data/doc/files/lib/MessageHandler_rb.html +0 -107
- data/doc/files/lib/Message_rb.html +0 -117
- data/doc/files/lib/ProjectFileParser_rb.html +0 -129
- data/doc/files/lib/Project_rb.html +0 -153
- data/doc/files/lib/PropertyList_rb.html +0 -107
- data/doc/files/lib/PropertySet_rb.html +0 -119
- data/doc/files/lib/PropertyTreeNode_rb.html +0 -107
- data/doc/files/lib/Query_rb.html +0 -117
- data/doc/files/lib/RTFNavigator_rb.html +0 -121
- data/doc/files/lib/RTFQuery_rb.html +0 -121
- data/doc/files/lib/RTFReport_rb.html +0 -119
- data/doc/files/lib/RealFormat_rb.html +0 -107
- data/doc/files/lib/RemoteServiceManager_rb.html +0 -117
- data/doc/files/lib/ReportServer_rb.html +0 -107
- data/doc/files/lib/ResourceScenario_rb.html +0 -117
- data/doc/files/lib/Resource_rb.html +0 -119
- data/doc/files/lib/RichTextDocument_rb.html +0 -121
- data/doc/files/lib/RichTextElement_rb.html +0 -121
- data/doc/files/lib/RichTextFunctionExample_rb.html +0 -121
- data/doc/files/lib/RichTextFunctionHandler_rb.html +0 -107
- data/doc/files/lib/RichTextParser_rb.html +0 -121
- data/doc/files/lib/RichTextScanner_rb.html +0 -117
- data/doc/files/lib/RichTextSnip_rb.html +0 -119
- data/doc/files/lib/RichTextSyntaxRules_rb.html +0 -107
- data/doc/files/lib/RichText_rb.html +0 -119
- data/doc/files/lib/ScenarioData_rb.html +0 -119
- data/doc/files/lib/Scenario_rb.html +0 -117
- data/doc/files/lib/Scoreboard_rb.html +0 -107
- data/doc/files/lib/ShiftAssignments_rb.html +0 -117
- data/doc/files/lib/ShiftScenario_rb.html +0 -117
- data/doc/files/lib/Shift_rb.html +0 -119
- data/doc/files/lib/SourceFileInfo_rb.html +0 -107
- data/doc/files/lib/SyntaxReference_rb.html +0 -123
- data/doc/files/lib/TOCEntry_rb.html +0 -119
- data/doc/files/lib/TableColumnDefinition_rb.html +0 -107
- data/doc/files/lib/TableOfContents_rb.html +0 -119
- data/doc/files/lib/TaskDependency_rb.html +0 -107
- data/doc/files/lib/TaskJuggler_rb.html +0 -125
- data/doc/files/lib/TaskScenario_rb.html +0 -117
- data/doc/files/lib/Task_rb.html +0 -119
- data/doc/files/lib/TextParser/Pattern_rb.html +0 -117
- data/doc/files/lib/TextParser/Rule_rb.html +0 -107
- data/doc/files/lib/TextParser/StackElement_rb.html +0 -107
- data/doc/files/lib/TextParser/TokenDoc_rb.html +0 -107
- data/doc/files/lib/TextParser_rb.html +0 -125
- data/doc/files/lib/TextScanner_rb.html +0 -129
- data/doc/files/lib/Tj3Config_rb.html +0 -119
- data/doc/files/lib/TjException_rb.html +0 -107
- data/doc/files/lib/TjTime_rb.html +0 -119
- data/doc/files/lib/TjpExample_rb.html +0 -117
- data/doc/files/lib/TjpSyntaxRules_rb.html +0 -107
- data/doc/files/lib/UTF8String_rb.html +0 -140
- data/doc/files/lib/UserManual_rb.html +0 -127
- data/doc/files/lib/WorkingHours_rb.html +0 -117
- data/doc/files/lib/XMLDocument_rb.html +0 -117
- data/doc/files/lib/XMLElement_rb.html +0 -117
- data/doc/files/lib/deep_copy_rb.html +0 -107
- data/doc/files/lib/reports/CSVFile_rb.html +0 -117
- data/doc/files/lib/reports/ColumnTable_rb.html +0 -117
- data/doc/files/lib/reports/GanttChart_rb.html +0 -123
- data/doc/files/lib/reports/GanttContainer_rb.html +0 -117
- data/doc/files/lib/reports/GanttHeaderScaleItem_rb.html +0 -107
- data/doc/files/lib/reports/GanttHeader_rb.html +0 -117
- data/doc/files/lib/reports/GanttLine_rb.html +0 -127
- data/doc/files/lib/reports/GanttLoadStack_rb.html +0 -117
- data/doc/files/lib/reports/GanttMilestone_rb.html +0 -117
- data/doc/files/lib/reports/GanttRouter_rb.html +0 -107
- data/doc/files/lib/reports/GanttTaskBar_rb.html +0 -117
- data/doc/files/lib/reports/HTMLGraphics_rb.html +0 -107
- data/doc/files/lib/reports/Navigator_rb.html +0 -117
- data/doc/files/lib/reports/ReportBase_rb.html +0 -107
- data/doc/files/lib/reports/ReportContext_rb.html +0 -107
- data/doc/files/lib/reports/ReportTableCell_rb.html +0 -107
- data/doc/files/lib/reports/ReportTableColumn_rb.html +0 -107
- data/doc/files/lib/reports/ReportTableLegend_rb.html +0 -107
- data/doc/files/lib/reports/ReportTableLine_rb.html +0 -117
- data/doc/files/lib/reports/ReportTable_rb.html +0 -119
- data/doc/files/lib/reports/Report_rb.html +0 -137
- data/doc/files/lib/reports/ResourceListRE_rb.html +0 -123
- data/doc/files/lib/reports/TableReport_rb.html +0 -125
- data/doc/files/lib/reports/TaskListRE_rb.html +0 -123
- data/doc/files/lib/reports/TextReport_rb.html +0 -117
- data/doc/files/lib/reports/TimeSheetReport_rb.html +0 -117
- data/doc/files/lib/reports/TjpExportRE_rb.html +0 -117
- data/doc/files/lib/taskjuggler3_rb.html +0 -298
- data/doc/files/lib/tj3client_rb.html +0 -280
- data/doc/files/lib/tj3man_rb.html +0 -190
- data/doc/fr_class_index.html +0 -345
- data/doc/fr_file_index.html +0 -247
- data/doc/fr_method_index.html +0 -2355
- data/doc/rdoc-style.css +0 -299
- data/lib/RemoteServiceManager.rb +0 -80
- data/lib/ReportServer.rb +0 -66
- data/test/TestSuite/HTML-Reports/Alerts.html +0 -172
- data/test/TestSuite/HTML-Reports/CellText.html +0 -758
- data/test/TestSuite/HTML-Reports/ColumnPeriods.html +0 -156
- data/test/TestSuite/HTML-Reports/IsOngoing.html +0 -172
- data/test/TestSuite/HTML-Reports/LogicalFunctions.html +0 -80
- data/test/TestSuite/HTML-Reports/Query.html +0 -31
- data/test/TestSuite/HTML-Reports/depArrows.html +0 -842
- data/test/TestSuite/Syntax/Correct/RawHTML.tjp +0 -31
- data/test/TestSuite/Syntax/Correct/icons/flag-green.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/flag-red.png +0 -0
- data/test/TestSuite/Syntax/Correct/icons/flag-yellow.png +0 -0
- data/test/TestSuite/Syntax/Correct/scripts/wz_tooltip.js +0 -1301
- data/test/TestSuite/Syntax/Errors/export_bad_extn.tjp +0 -9
@@ -0,0 +1,355 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = SheetReceiver.rb -- The TaskJuggler III Project Management Software
|
5
|
+
#
|
6
|
+
# Copyright (c) 2006, 2007, 2008, 2009, 2010 by Chris Schlaeger <cs@kde.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'digest/md5'
|
14
|
+
require 'mail'
|
15
|
+
require 'open4'
|
16
|
+
require 'yaml'
|
17
|
+
require 'SheetHandlerBase'
|
18
|
+
|
19
|
+
class TaskJuggler
|
20
|
+
|
21
|
+
class SheetReceiver < SheetHandlerBase
|
22
|
+
|
23
|
+
def initialize(appName, type)
|
24
|
+
super(appName)
|
25
|
+
|
26
|
+
@sheetType = type
|
27
|
+
# The following settings must be set by the deriving class.
|
28
|
+
# Sheet type specific option for tj3client
|
29
|
+
@tj3clientOption = nil
|
30
|
+
# Base directory to store received sheets
|
31
|
+
@sheetDir = nil
|
32
|
+
# Base directory where to find the resource file.
|
33
|
+
@templateDir = nil
|
34
|
+
# Directory to store the failed emails.
|
35
|
+
@failedMailsDir = nil
|
36
|
+
# Directory to store the failed sheets
|
37
|
+
@failedSheetsDir = nil
|
38
|
+
# File that holds the acceptable signatures.
|
39
|
+
@signatureFile = nil
|
40
|
+
# The log file
|
41
|
+
@logFile = nil
|
42
|
+
|
43
|
+
# Regular expressions to identify a status sheet.
|
44
|
+
@sheetHeader = /^[ ]*statussheet\s([a-z][a-z0-9_]*)\s([0-9]*-[0-9]*-[0-9]*)/
|
45
|
+
# Regular expression to extract the sheet signature (date).
|
46
|
+
@signatureFilter = /^[ ]*statussheet\s[a-z][a-z0-9_]*\s([0-9:\-+]*)/
|
47
|
+
# The email address of the submitter of the sheet.
|
48
|
+
@submitter = nil
|
49
|
+
# The resource ID of the submitter.
|
50
|
+
@resourceId = nil
|
51
|
+
# The stdout content from tj3client
|
52
|
+
@report = nil
|
53
|
+
# The stderr content from tj3client
|
54
|
+
@warnings = nil
|
55
|
+
|
56
|
+
# The extracted sheet text.
|
57
|
+
@sheet = nil
|
58
|
+
# Will indicate whether the sheet was attached or in mail body
|
59
|
+
@sheetWasAttached = true
|
60
|
+
# The end date of the reporting period.
|
61
|
+
@date = nil
|
62
|
+
# The id of the incomming message.
|
63
|
+
@messageId = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
# Read the sheet from $stdin in email format. Extract the sheet from the
|
67
|
+
# attachments or body and check it. If ok, send back a summary, otherwise
|
68
|
+
# the error message.
|
69
|
+
# The actual check is done by a tj3 server process that is accessed via
|
70
|
+
# tj3client.
|
71
|
+
def processEmail
|
72
|
+
setWorkingDir
|
73
|
+
|
74
|
+
createDirectories
|
75
|
+
|
76
|
+
mail = Mail.new($stdin.read)
|
77
|
+
|
78
|
+
# Who sent this email?
|
79
|
+
@submitter = mail.from.respond_to?('[]') ? mail.from[0] : mail.from
|
80
|
+
# Getting the message ID.
|
81
|
+
@messageId = mail.message_id || 'unknown'
|
82
|
+
@idDigest = Digest::MD5.hexdigest(@messageId)
|
83
|
+
info("Processing #{@sheetType} mail from #{@submitter} " +
|
84
|
+
"with ID #{@messageId} (#{@idDigest})")
|
85
|
+
|
86
|
+
# Store the mail in the failedMailsDir in case something goes wrong.
|
87
|
+
File.open("#{@failedMailsDir}/#{@idDigest}", 'w') do |f|
|
88
|
+
f.write(mail)
|
89
|
+
end
|
90
|
+
|
91
|
+
# First we search the attachments and then the body.
|
92
|
+
mail.attachments.each do |attachment|
|
93
|
+
# We are looking for an attached file with a .tji extension.
|
94
|
+
fileName = attachment.filename
|
95
|
+
next unless fileName && fileName[-4..-1] == '.tji'
|
96
|
+
|
97
|
+
# Further inspect the attachment. If we could process it, we are done.
|
98
|
+
return true if processSheet(attachment.body.decoded)
|
99
|
+
end
|
100
|
+
# None of the attachements worked, so let's try the mail body.
|
101
|
+
@sheetWasAttached = false
|
102
|
+
return true if processSheet(mail.body.decoded)
|
103
|
+
|
104
|
+
error(<<"EOT"
|
105
|
+
No #{@sheetType} sheet found in email. Please make sure the header syntax is
|
106
|
+
correct and contained in a single line that starts at the begining of the
|
107
|
+
line. If you had the #{@sheetType} sheet attached, the file name must have a
|
108
|
+
'.tji' extension to be found.
|
109
|
+
EOT
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
# Isolate the actual syntax from _sheet_ and process it.
|
116
|
+
def processSheet(sheet)
|
117
|
+
# Store the detected sheet so we can include it with error reports if
|
118
|
+
# needed.
|
119
|
+
@sheet = cutOut(fixLineBreaks(sheet))
|
120
|
+
# A valid sheet must have the poper header line.
|
121
|
+
if @sheetHeader.match(@sheet)
|
122
|
+
checkSignature(@sheet)
|
123
|
+
# Extract the resource ID and the end date from the sheet.
|
124
|
+
matches = @sheetHeader.match(@sheet)
|
125
|
+
@resourceId, @date = matches[1..2]
|
126
|
+
# Email answers will only go the email address on file!
|
127
|
+
@submitter = getResourceEmail(@resourceId)
|
128
|
+
info("Found #{@sheetWasAttached ? 'attached ' : ''}sheet for " +
|
129
|
+
"#{@resourceId} dated #{@date}")
|
130
|
+
# Ok, found. Now check the full sheet.
|
131
|
+
if checkSheet(@sheet)
|
132
|
+
# Everything is fine. Store it away.
|
133
|
+
fileSheet(@sheet)
|
134
|
+
# Remove the mail from the failedMailsDir
|
135
|
+
File.delete("#{@failedMailsDir}/#{@idDigest}")
|
136
|
+
info("Accepted sheet for #{@resourceId} dated #{@date}")
|
137
|
+
return true
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def checkSheet(sheet)
|
143
|
+
err = ''
|
144
|
+
status = nil
|
145
|
+
begin
|
146
|
+
# Save a copy of the sheet for debugging purposes.
|
147
|
+
File.open("#{@failedSheetsDir}/#{@resourceId}-#{@date}.tji", 'w') do |f|
|
148
|
+
f.write(sheet)
|
149
|
+
end
|
150
|
+
command = "tj3client --silent #{@tj3clientOption} #{@projectId} ."
|
151
|
+
status = Open4.popen4(command) do |pid, stdin, stdout, stderr|
|
152
|
+
# Send the report to the tj3client process via stdin.
|
153
|
+
stdin.write(sheet)
|
154
|
+
stdin.close
|
155
|
+
@report = stdout.read
|
156
|
+
@warnings = stderr.read
|
157
|
+
end
|
158
|
+
rescue
|
159
|
+
fatal("Cannot check #{@sheetType} sheet: #{$!}")
|
160
|
+
end
|
161
|
+
if status.exitstatus == 0
|
162
|
+
File.delete("#{@failedSheetsDir}/#{@resourceId}-#{@date}.tji")
|
163
|
+
return true
|
164
|
+
end
|
165
|
+
|
166
|
+
# The exit status was not 0. The stderr output should not be empty and
|
167
|
+
# will contain error and warning messages.
|
168
|
+
error(@warnings)
|
169
|
+
end
|
170
|
+
|
171
|
+
def fileSheet(sheet)
|
172
|
+
# Create the appropriate directory structure if it doesn't exist.
|
173
|
+
dir = "#{@sheetDir}/#{@date}"
|
174
|
+
fileName = "#{dir}/#{@resourceId}_#{@date}.tji"
|
175
|
+
newDir = false
|
176
|
+
begin
|
177
|
+
unless File.directory?(dir)
|
178
|
+
Dir.mkdir(dir)
|
179
|
+
addToScm('Adding new directory', dir)
|
180
|
+
newDir = true
|
181
|
+
end
|
182
|
+
File.open(fileName, 'w') { |f| f.write(sheet) }
|
183
|
+
addToScm("Adding/updating #{fileName}", fileName)
|
184
|
+
rescue
|
185
|
+
fatal("Cannot store #{@sheetType} sheet #{fileName}: #{$!}")
|
186
|
+
return
|
187
|
+
end
|
188
|
+
|
189
|
+
# Create or update the file that includes all *.tji in the directory.
|
190
|
+
generateInclusionFile(dir)
|
191
|
+
|
192
|
+
if newDir
|
193
|
+
# Add the new directory to the parent all.tji file.
|
194
|
+
allFile = "#{@sheetDir}/all.tji"
|
195
|
+
File.open(allFile, 'a') do |f|
|
196
|
+
f.write("\ninclude '#{@date}/all.tji' { }")
|
197
|
+
end
|
198
|
+
addToScm('Adding new directory to all.tji', allFile)
|
199
|
+
end
|
200
|
+
|
201
|
+
text = <<"EOT"
|
202
|
+
Report from #{getResourceName} for the period ending #{@date}:
|
203
|
+
|
204
|
+
EOT
|
205
|
+
|
206
|
+
# Add warnings if we had any.
|
207
|
+
unless @warnings.empty?
|
208
|
+
text += <<"EOT"
|
209
|
+
Your report does contain some issues that you may want to fix or address with
|
210
|
+
your manager or project manager:
|
211
|
+
|
212
|
+
#{@warnings}
|
213
|
+
|
214
|
+
EOT
|
215
|
+
end
|
216
|
+
|
217
|
+
# Append the pretty printed version of the submitted status sheet.
|
218
|
+
text += @report
|
219
|
+
|
220
|
+
# Send out the email.
|
221
|
+
sendEmail(@submitter, "Report from #{getResourceName} for #{@date}", text,
|
222
|
+
nil, nil, @messageId)
|
223
|
+
true
|
224
|
+
end
|
225
|
+
|
226
|
+
# Generate or update a file the contains 'include' statements for all the
|
227
|
+
# .tji files in the provided directory. The generated file will be in this
|
228
|
+
# directory as well.
|
229
|
+
def generateInclusionFile(dir)
|
230
|
+
pwd = Dir.pwd
|
231
|
+
begin
|
232
|
+
Dir.chdir(dir)
|
233
|
+
File.open('all.tji', 'w') do |file|
|
234
|
+
Dir.glob('*.tji').each do |tji|
|
235
|
+
file.puts("include '#{tji}' { }") unless tji == 'all.tji'
|
236
|
+
end
|
237
|
+
end
|
238
|
+
rescue
|
239
|
+
error("Can't create inclusion file: #{$!}")
|
240
|
+
ensure
|
241
|
+
Dir.chdir(pwd)
|
242
|
+
end
|
243
|
+
# Report the change to the SCM handler.
|
244
|
+
addToScm('Adding/updating summary include file.', "#{dir}/all.tji")
|
245
|
+
end
|
246
|
+
|
247
|
+
def checkSignature(sheet)
|
248
|
+
if matches = @signatureFilter.match(sheet)
|
249
|
+
interval = matches[1]
|
250
|
+
else
|
251
|
+
fatal("No #{@sheetType}sheet header found")
|
252
|
+
end
|
253
|
+
|
254
|
+
acceptedSignatures = []
|
255
|
+
if File.exist?(@signatureFile)
|
256
|
+
File.open(@signatureFile, 'r') do |file|
|
257
|
+
acceptedSignatures = file.readlines
|
258
|
+
end
|
259
|
+
acceptedSignatures.map! { |s| s.chomp }
|
260
|
+
acceptedSignatures.delete_if { |s| s.chomp.empty? }
|
261
|
+
else
|
262
|
+
error("#{@signatureFile} does not exist yet.")
|
263
|
+
end
|
264
|
+
|
265
|
+
unless acceptedSignatures.include?(interval)
|
266
|
+
error(<<"EOT"
|
267
|
+
The reporting period #{interval}
|
268
|
+
was not accepted! Either you have modified the sheet header,
|
269
|
+
you are submitting the sheet too late or too early.
|
270
|
+
EOT
|
271
|
+
)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def createDirectories
|
276
|
+
[ @sheetDir, @failedMailsDir, @failedSheetsDir ].each do |dir|
|
277
|
+
unless File.directory?(dir)
|
278
|
+
info("Creating directory #{dir}")
|
279
|
+
Dir.mkdir(dir)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def error(message)
|
285
|
+
$stderr.puts message if @outputLevel >= 1
|
286
|
+
|
287
|
+
log('ERROR', "#{message}") if @logLevel >= 1
|
288
|
+
|
289
|
+
# Append the submitted sheet for further tries. We may run into encoding
|
290
|
+
# errors here. In this case we send the answer without the incoming time
|
291
|
+
# sheet.
|
292
|
+
begin
|
293
|
+
message += "\n" + @sheet if @sheet && !@sheetWasAttached
|
294
|
+
rescue
|
295
|
+
end
|
296
|
+
|
297
|
+
sendEmail(@submitter, 'Your time sheet submission failed!', message)
|
298
|
+
|
299
|
+
exit 1
|
300
|
+
end
|
301
|
+
|
302
|
+
def fatal(message)
|
303
|
+
log('FATAL', "#{message}")
|
304
|
+
|
305
|
+
# Append the submitted sheet for further tries.
|
306
|
+
message += "\n" + @sheet if @sheet
|
307
|
+
|
308
|
+
sendEmail(@submitter, 'Temporary server error', <<"EOT"
|
309
|
+
We are sorry! The #{@sheetType} sheet server detected a configuration
|
310
|
+
problem and is temporarily out of service. The administrator
|
311
|
+
has been notified and will try to rectify the situation as
|
312
|
+
soon as possible. Please re-submit your #{@sheetType} sheet later!
|
313
|
+
EOT
|
314
|
+
)
|
315
|
+
exit 1
|
316
|
+
end
|
317
|
+
|
318
|
+
|
319
|
+
# Load tye resources.yml YAML file into the @resourceList variable.
|
320
|
+
# The format is Array with one entry per resource. The entry is an Array
|
321
|
+
# with 3 fields: ID, name and email. All fields are String objects.
|
322
|
+
def getResourceList
|
323
|
+
fatal('@date not set') unless @date
|
324
|
+
|
325
|
+
fileName = "#{@templateDir}/#{@date}/resources.yml"
|
326
|
+
begin
|
327
|
+
@resourceList = YAML.load(File.read(fileName))
|
328
|
+
info("#{@resourceList.length} resources loaded")
|
329
|
+
rescue
|
330
|
+
error("Cannot read resource file #{fileName}: #{$!}")
|
331
|
+
end
|
332
|
+
@resourceList
|
333
|
+
end
|
334
|
+
|
335
|
+
def getResourceEmail(id = @resourceId)
|
336
|
+
getResourceList unless @resourceList
|
337
|
+
|
338
|
+
@resourceList.each do |resource|
|
339
|
+
return resource[2] if resource[0] == id
|
340
|
+
end
|
341
|
+
error("Resource ID '#{id}' not found in list")
|
342
|
+
end
|
343
|
+
|
344
|
+
def getResourceName(id = @resourceId)
|
345
|
+
getResourceList unless @resourceList
|
346
|
+
|
347
|
+
@resourceList.each do |resource|
|
348
|
+
return resource[1] if resource[0] == id
|
349
|
+
end
|
350
|
+
error("Resource ID '#{id}' not found in list")
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|
354
|
+
|
355
|
+
end
|
data/lib/SheetSender.rb
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = SheetSender.rb -- The TaskJuggler III Project Management Software
|
5
|
+
#
|
6
|
+
# Copyright (c) 2006, 2007, 2008, 2009, 2010 by Chris Schlaeger <cs@kde.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'open4'
|
14
|
+
require 'mail'
|
15
|
+
require 'yaml'
|
16
|
+
require 'SheetHandlerBase'
|
17
|
+
|
18
|
+
class TaskJuggler
|
19
|
+
|
20
|
+
# A base class for sheet senders.
|
21
|
+
class SheetSender < SheetHandlerBase
|
22
|
+
|
23
|
+
attr_accessor :force, :intervalDuration
|
24
|
+
|
25
|
+
def initialize(appName, type)
|
26
|
+
super(appName)
|
27
|
+
|
28
|
+
@sheetType = type
|
29
|
+
# The following settings must be provided by the deriving class.
|
30
|
+
# This is a LogicalExpression string that controls what resources should
|
31
|
+
# not be getting a report sheet template.
|
32
|
+
@hideResource = nil
|
33
|
+
# This file contains the signature (date or interval) that the
|
34
|
+
# SheetReceiver will accept as a valid signature.
|
35
|
+
@signatureFile = nil
|
36
|
+
# The base directory of the sheet templates.
|
37
|
+
@templateDir = nil
|
38
|
+
# When true, existing templates will be regenerated and send out again.
|
39
|
+
# Otherwise the existing template will not be send out again.
|
40
|
+
@force = false
|
41
|
+
|
42
|
+
@signatureFilter = nil
|
43
|
+
@introText = nil
|
44
|
+
|
45
|
+
# The end date of the reported interval.
|
46
|
+
@date = Time.new.strftime('%Y-%m-%d')
|
47
|
+
# Determines the length of the reported interval.
|
48
|
+
@intervalDuration = '1w'
|
49
|
+
# We need this to determine if we already sent out a report.
|
50
|
+
@timeStamp = Time.new
|
51
|
+
end
|
52
|
+
|
53
|
+
# Send out report templates to a list of project resources. The resources
|
54
|
+
# are selected by the @hideResource filter expression and can be further
|
55
|
+
# limited with a list of resource IDs passed by _resourceList_.
|
56
|
+
def sendTemplates(resourceList)
|
57
|
+
setWorkingDir
|
58
|
+
createDirectories
|
59
|
+
|
60
|
+
resources = genResourceList(resourceList)
|
61
|
+
genTemplates(resources)
|
62
|
+
sendReportTemplates(resources)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def createDirectories
|
68
|
+
unless File.directory?(@templateDir)
|
69
|
+
warning("Creating directory #{@templateDir}")
|
70
|
+
Dir.mkdir(@templateDir)
|
71
|
+
end
|
72
|
+
@templateDir += "/#{@date}"
|
73
|
+
unless File.directory?(@templateDir)
|
74
|
+
Dir.mkdir(@templateDir)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def genResourceList(resourceList)
|
79
|
+
list = []
|
80
|
+
info('Retrieving resource list...')
|
81
|
+
reportDef = <<"EOF"
|
82
|
+
resourcereport rl_21497214 '.' {
|
83
|
+
formats csv
|
84
|
+
columns id, name, email, effort, freework
|
85
|
+
hideresource #{@hideResource}
|
86
|
+
sortresources id.up
|
87
|
+
loadunit days
|
88
|
+
period %{#{@date} - 1w} +1w
|
89
|
+
}
|
90
|
+
EOF
|
91
|
+
report = generateReport('rl_21497214', reportDef)
|
92
|
+
first = true
|
93
|
+
report.each_line do |line|
|
94
|
+
if first
|
95
|
+
first = false
|
96
|
+
next
|
97
|
+
end
|
98
|
+
id, name, email, effort, free = line.split(';')
|
99
|
+
if email.empty?
|
100
|
+
error("Resource '#{id}' must have a valid email address")
|
101
|
+
end
|
102
|
+
# Convert effort and free values into Float objects.
|
103
|
+
effort = effort.to_f
|
104
|
+
free = free.to_f
|
105
|
+
|
106
|
+
# Ignore resources that are on vacation for the whole period.
|
107
|
+
if effort == 0.0 && free == 0.0
|
108
|
+
info("Resource '#{id}' was on vacation the whole period")
|
109
|
+
next
|
110
|
+
end
|
111
|
+
|
112
|
+
list << [ id, name, email, effort, free ]
|
113
|
+
end
|
114
|
+
|
115
|
+
# Save the resource list to a file. We'll need it in the receiver again.
|
116
|
+
begin
|
117
|
+
fileName = @templateDir + '/resources.yml'
|
118
|
+
File.open(fileName, 'w') do |file|
|
119
|
+
YAML.dump(list, file)
|
120
|
+
end
|
121
|
+
rescue
|
122
|
+
error("Saving of #{fileName} failed: #{$!}")
|
123
|
+
end
|
124
|
+
|
125
|
+
unless resourceList.empty?
|
126
|
+
# When the user specified resource list is empty, we generate templates
|
127
|
+
# for all users that don't match the @hideResource filter. Otherwise we
|
128
|
+
# only generate templates for those in the list and that are not hidden
|
129
|
+
# by the filter.
|
130
|
+
list.delete_if { |item| !resourceList.include?(item[0]) }
|
131
|
+
end
|
132
|
+
|
133
|
+
error('genResourceList: list is empty') if list.empty?
|
134
|
+
|
135
|
+
info("#{list.length} resources found")
|
136
|
+
list
|
137
|
+
end
|
138
|
+
|
139
|
+
def genTemplates(resources)
|
140
|
+
firstTemplateFile = nil
|
141
|
+
resources.each do |resInfo|
|
142
|
+
res = resInfo[0]
|
143
|
+
info("Generating template for #{res}...")
|
144
|
+
reportId = "sheet_template_#{res}"
|
145
|
+
templateFile = "#{@templateDir}/#{res}_#{@date}"
|
146
|
+
# We use the first template file to get the sheet interval.
|
147
|
+
firstTemplateFile = templateFile + '.tji' unless firstTemplateFile
|
148
|
+
|
149
|
+
# Don't re-generate already existing templates unless we are in force
|
150
|
+
# mode. We probably have sent them out earlier with a manual trigger.
|
151
|
+
if !@force && File.exist?(templateFile + '.tji')
|
152
|
+
info("Skipping already existing #{templateFile}.tji.")
|
153
|
+
next
|
154
|
+
end
|
155
|
+
|
156
|
+
reportDef = <<"EOT"
|
157
|
+
#{@sheetType}sheetreport #{reportId} \"#{templateFile}\" {
|
158
|
+
hideresource ~(plan.id = \"#{res}\")
|
159
|
+
period %{#{@date} - #{@intervalDuration}} +#{@intervalDuration}
|
160
|
+
sorttasks id.up
|
161
|
+
}
|
162
|
+
EOT
|
163
|
+
generateReport(reportId, reportDef)
|
164
|
+
end
|
165
|
+
enableSignatureForReporting(firstTemplateFile)
|
166
|
+
end
|
167
|
+
|
168
|
+
def sendReportTemplates(resources)
|
169
|
+
resources.each do |id, name, email|
|
170
|
+
attachment = "#{@templateDir}/#{id}_#{@date}.tji"
|
171
|
+
unless File.exist?(attachment)
|
172
|
+
error("sendReportTemplates: " +
|
173
|
+
"#{@sheetType} sheet #{attachment} for #{name} not found")
|
174
|
+
end
|
175
|
+
# Don't send out old templates again. @timeStamp has a higher
|
176
|
+
# resolution. We add 1s to avoid truncation errors.
|
177
|
+
if (File.mtime(attachment) + 1) < @timeStamp
|
178
|
+
info("Old template #{attachment} found. Not sending it out.")
|
179
|
+
next
|
180
|
+
end
|
181
|
+
|
182
|
+
message = " Hello #{name}!\n\n#{@introText}" + File.read(attachment)
|
183
|
+
|
184
|
+
sendEmail(email, "Your weekly report template for #{@date}",
|
185
|
+
message, attachment)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def enableSignatureForReporting(templateFile)
|
190
|
+
signature = nil
|
191
|
+
# That's a pretty bad hack to make reasonably certain that the tj3 server
|
192
|
+
# process has put the complete file into the file system.
|
193
|
+
i = 0
|
194
|
+
begin
|
195
|
+
if File.exist?(templateFile)
|
196
|
+
File.open(templateFile, 'r') do |file|
|
197
|
+
while (line = file.gets)
|
198
|
+
if matches = @signatureFilter.match(line)
|
199
|
+
signature = matches[1]
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
i += 1
|
205
|
+
# If the file doesn't exist yet or the cannot yet be read, wait for
|
206
|
+
# 300ms. We try this 100 times.
|
207
|
+
sleep(0.3) unless signature
|
208
|
+
end while signature.nil? && i < 100
|
209
|
+
unless signature
|
210
|
+
error("enableSignatureForReporting: Cannot find signature in file " +
|
211
|
+
"#{templateFile}")
|
212
|
+
end
|
213
|
+
|
214
|
+
acceptedSignatures = []
|
215
|
+
if File.exist?(@signatureFile)
|
216
|
+
File.open(@signatureFile, 'r') do |file|
|
217
|
+
acceptedSignatures = file.readlines
|
218
|
+
end
|
219
|
+
acceptedSignatures.map! { |s| s.chomp }
|
220
|
+
acceptedSignatures.delete_if { |s| s.chomp.empty? }
|
221
|
+
else
|
222
|
+
info("#{@signatureFile} does not exist yet.")
|
223
|
+
end
|
224
|
+
unless acceptedSignatures.include?(signature)
|
225
|
+
# Add the new signature
|
226
|
+
info("Adding #{signature} to #{@signatureFile}")
|
227
|
+
acceptedSignatures << signature
|
228
|
+
# And write back the adapted file.
|
229
|
+
File.open(@signatureFile, 'w') do |file|
|
230
|
+
acceptedSignatures.each do |iv|
|
231
|
+
file.write("#{iv}\n")
|
232
|
+
end
|
233
|
+
end
|
234
|
+
else
|
235
|
+
info("Signature #{signature} is already listed in #{@signatureFile}")
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def generateReport(id, reportDef)
|
240
|
+
out = ''
|
241
|
+
err = ''
|
242
|
+
begin
|
243
|
+
command = "tj3client --silent report #{@projectId} #{id} = ."
|
244
|
+
status = Open4.popen4(command) do |pid, stdin, stdout, stderr|
|
245
|
+
# Send the report definition to the tj3client process via stdin.
|
246
|
+
stdin.write(reportDef)
|
247
|
+
stdin.close
|
248
|
+
# Retrieve the output
|
249
|
+
out = stdout.read
|
250
|
+
err = stderr.read
|
251
|
+
end
|
252
|
+
if status.exitstatus != 0
|
253
|
+
error("generateReport: #{err}")
|
254
|
+
end
|
255
|
+
rescue
|
256
|
+
error("generateReport: Report generation failed: #{$!}")
|
257
|
+
end
|
258
|
+
out
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|