diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py index d80d641d0f9e2ddcd2b80d95df22d8aa3be4126e..7bfb0f1a186c72099d037c16b8268377ebe254a3 100644 --- a/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py +++ b/SAS/TMSS/backend/src/tmss/tmssapp/viewsets/specification.py @@ -1082,10 +1082,34 @@ class SchedulingUnitBlueprintNestedViewSet(LOFARNestedViewSet): else: return models.SchedulingUnitBlueprint.objects.all() +class TaskDraftPropertyFilter(property_filters.PropertyFilterSet): + id = NumberInFilter(field_name='id', lookup_expr='in') + id_min = filters.NumberFilter(field_name='id', lookup_expr='gte') + id_max = filters.NumberFilter(field_name='id', lookup_expr='lte') + scheduling_unit_draft = ModelChoiceInFilter(field_name='scheduling_unit_draft', lookup_expr='in', queryset=models.SchedulingUnitDraft.objects.all()) + scheduling_unit_draft_min = filters.NumberFilter(field_name='scheduling_unit_draft__id', lookup_expr='gte') + scheduling_unit_draft_max = filters.NumberFilter(field_name='scheduling_unit_draft__id', lookup_expr='lte') + scheduling_unit_draft_name = filters.CharFilter(field_name='scheduling_unit_draft__name', lookup_expr='icontains') + task_blueprints = filters.ModelMultipleChoiceFilter(field_name='task_blueprints', queryset=models.TaskBlueprint.objects.all()) + duration_min = property_filters.PropertyDurationFilter(field_name='duration', lookup_expr='gte') + duration_max = property_filters.PropertyDurationFilter(field_name='duration', lookup_expr='lte') + created_at = filters.IsoDateTimeFromToRangeFilter(field_name='created_at') + updated_at = filters.IsoDateTimeFromToRangeFilter(field_name='updated_at') + relative_start_time_min = property_filters.PropertyDurationFilter(field_name='relative_start_time', lookup_expr='gte') + relative_start_time_max = property_filters.PropertyDurationFilter(field_name='relative_start_time', lookup_expr='lte') + relative_stop_time_min = property_filters.PropertyDurationFilter(field_name='relative_stop_time', lookup_expr='gte') + relative_stop_time_max = property_filters.PropertyDurationFilter(field_name='relative_stop_time', lookup_expr='lte') + + class Meta: + model = models.TaskDraft + fields = '__all__' + filter_overrides = FILTER_OVERRIDES + class TaskDraftViewSet(LOFARViewSet): queryset = models.TaskDraft.objects.all() serializer_class = serializers.TaskDraftSerializer + filter_class = TaskDraftPropertyFilter # prefetch all reverse related references from other models on their related_name to avoid a ton of duplicate queries queryset = queryset.prefetch_related('first_scheduling_relation') \ @@ -1209,9 +1233,42 @@ class TaskDraftNestedViewSet(LOFARNestedViewSet): return models.TaskDraft.objects.all() +class TaskBlueprintPropertyFilter(property_filters.PropertyFilterSet): + id = NumberInFilter(field_name='id', lookup_expr='in') + id_min = filters.NumberFilter(field_name='id', lookup_expr='gte') + id_max = filters.NumberFilter(field_name='id', lookup_expr='lte') + scheduling_unit_blueprint = ModelChoiceInFilter(field_name='scheduling_unit_blueprint', lookup_expr='in', queryset=models.SchedulingUnitBlueprint.objects.all()) + scheduling_unit_blueprint_min = filters.NumberFilter(field_name='scheduling_unit_blueprint__id', lookup_expr='gte') + scheduling_unit_blueprint_max = filters.NumberFilter(field_name='scheduling_unit_blueprint__id', lookup_expr='lte') + scheduling_unit_blueprint_name = filters.CharFilter(field_name='scheduling_unit_blueprint__name', lookup_expr='icontains') + draft = ModelChoiceInFilter(field_name='draft', lookup_expr='in', queryset=models.TaskDraft.objects.all()) + draft_min = filters.NumberFilter(field_name='draft__id', lookup_expr='gte') + draft_max = filters.NumberFilter(field_name='draft__id', lookup_expr='lte') + duration_min = property_filters.PropertyDurationFilter(field_name='duration', lookup_expr='gte') + duration_max = property_filters.PropertyDurationFilter(field_name='duration', lookup_expr='lte') + created_at = filters.IsoDateTimeFromToRangeFilter(field_name='created_at') + updated_at = filters.IsoDateTimeFromToRangeFilter(field_name='updated_at') + relative_start_time_min = property_filters.PropertyDurationFilter(field_name='relative_start_time', lookup_expr='gte') + relative_start_time_max = property_filters.PropertyDurationFilter(field_name='relative_start_time', lookup_expr='lte') + relative_stop_time_min = property_filters.PropertyDurationFilter(field_name='relative_stop_time', lookup_expr='gte') + relative_stop_time_max = property_filters.PropertyDurationFilter(field_name='relative_stop_time', lookup_expr='lte') + start_time = property_filters.PropertyIsoDateTimeFromToRangeFilter(field_name='start_time') + stop_time = property_filters.PropertyIsoDateTimeFromToRangeFilter(field_name='stop_time') + status = property_filters.PropertyChoiceFilter(field_name='status', choices=tuple((i.value, i.value) for i in models.SubtaskState.Choices), lookup_expr='iexact') + subtasks = filters.ModelMultipleChoiceFilter(field_name='subtasks', queryset=models.Subtask.objects.all()) + subtasks_min = filters.NumberFilter(field_name='subtasks__id', lookup_expr='gte') + subtasks_max = filters.NumberFilter(field_name='subtasks__id', lookup_expr='lte') + + class Meta: + model = models.TaskBlueprint + fields = '__all__' + filter_overrides = FILTER_OVERRIDES + + class TaskBlueprintViewSet(LOFARViewSet): queryset = models.TaskBlueprint.objects.all() serializer_class = serializers.TaskBlueprintSerializer + filter_class = TaskBlueprintPropertyFilter # prefetch all reverse related references from other models on their related_name to avoid a ton of duplicate queries queryset = queryset.prefetch_related('first_scheduling_relation')\ diff --git a/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py b/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py index 1abe2b26896900fa7bfc9c36b3a7be3401fadf80..05a4a49fd9ec04920bc124f172e8c2f110994a23 100755 --- a/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py +++ b/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py @@ -1876,6 +1876,71 @@ class TaskDraftTestCase(unittest.TestCase): GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?copy_reason=gibberish', 400) + def test_TaskDraft_filters_for_TaskBlueprints(self): + + # setup + task_draft_1 = models.TaskDraft.objects.create(**TaskDraft_test_data("td_%s" % uuid.uuid4())) + task_draft_2 = models.TaskDraft.objects.create(**TaskDraft_test_data("td_%s" % uuid.uuid4())) + task_draft_3 = models.TaskDraft.objects.create(**TaskDraft_test_data("td_%s" % uuid.uuid4())) + task_blueprint_1 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data()) + task_blueprint_1.draft = task_draft_1 + task_blueprint_1.save() + task_blueprint_2 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data()) + task_blueprint_2.draft = task_draft_2 + task_blueprint_2.save() + task_blueprint_3 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data()) + task_blueprint_3.draft = task_draft_3 + task_blueprint_3.save() + + # assert + response_1 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?task_blueprints=%s' % task_blueprint_1.id, 200) + response_2 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?task_blueprints=%s' % task_blueprint_2.id, 200) + response_3 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?task_blueprints=%s&task_blueprints=%s' % (task_blueprint_1.id, task_blueprint_3.id), 200) + GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?task_blueprints=gibberish', 400) + self.assertIn(task_draft_1.name, str(response_1)) + self.assertNotIn(task_draft_2.name, str(response_1)) + self.assertNotIn(task_draft_3.name, str(response_1)) + self.assertNotIn(task_draft_1.name, str(response_2)) + self.assertIn(task_draft_2.name, str(response_2)) + self.assertNotIn(task_draft_3.name, str(response_2)) + self.assertIn(task_draft_1.name, str(response_3)) + self.assertNotIn(task_draft_2.name, str(response_3)) + self.assertIn(task_draft_3.name, str(response_3)) + + def test_TaskDraft_filters_for_SchedulingUnitDraft(self): + + # setup + su_draft_1 = models.SchedulingUnitDraft.objects.create(**SchedulingUnitDraft_test_data("sud_%s" % uuid.uuid4())) + su_draft_2 = models.SchedulingUnitDraft.objects.create(**SchedulingUnitDraft_test_data("sud_%s" % uuid.uuid4())) + su_draft_3 = models.SchedulingUnitDraft.objects.create(**SchedulingUnitDraft_test_data("sud_%s" % uuid.uuid4())) + task_draft_1 = models.TaskDraft.objects.create(**TaskDraft_test_data("td_%s" % uuid.uuid4(), scheduling_unit_draft=su_draft_1)) + task_draft_2 = models.TaskDraft.objects.create(**TaskDraft_test_data("td_%s" % uuid.uuid4(), scheduling_unit_draft=su_draft_2)) + task_draft_3 = models.TaskDraft.objects.create(**TaskDraft_test_data("td_%s" % uuid.uuid4(), scheduling_unit_draft=su_draft_3)) + + # assert + response_1 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?scheduling_unit_draft=%s' % su_draft_1.id, 200) + response_2 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?scheduling_unit_draft=%s,%s' % (su_draft_2.id, su_draft_3.id), 200) + response_3 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?scheduling_unit_draft_min=%s&scheduling_unit_draft_max=%s' % (su_draft_3.id, su_draft_3.id), 200) + response_4 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?scheduling_unit_draft_name=%s' % su_draft_2.name[:-3], 200) + GET_and_assert_equal_expected_code(self, BASE_URL + '/task_draft/?scheduling_unit_draft=%s' % 9999999, 400) + self.assertEqual(response_1['count'], 1) + self.assertIn(task_draft_1.name, str(response_1)) + self.assertNotIn(task_draft_2.name, str(response_1)) + self.assertNotIn(task_draft_3.name, str(response_1)) + self.assertEqual(response_2['count'], 2) + self.assertNotIn(task_draft_1.name, str(response_2)) + self.assertIn(task_draft_2.name, str(response_2)) + self.assertIn(task_draft_3.name, str(response_2)) + self.assertEqual(response_3['count'], 1) + self.assertNotIn(task_draft_1.name, str(response_3)) + self.assertNotIn(task_draft_2.name, str(response_3)) + self.assertIn(task_draft_3.name, str(response_3)) + self.assertEqual(response_4['count'], 1) + self.assertNotIn(task_draft_1.name, str(response_4)) + self.assertIn(task_draft_2.name, str(response_4)) + self.assertNotIn(task_draft_3.name, str(response_4)) + + class TaskRelationDraftTestCase(unittest.TestCase): @classmethod def setUpClass(cls) -> None: @@ -2535,25 +2600,116 @@ class TaskBlueprintTestCase(unittest.TestCase): response_data = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/%s/' % task_blueprint.id, 200) assertUrlList(self, response_data['subtasks'], [subtask_1, subtask_2]) - @unittest.skip("This test is dependend on previous tests (in the results list). ToDo: fix it.") def test_TaskBlueprint_contains_lists_of_related_TaskRelationBlueprint(self): # setup - test_data_1 = TaskBlueprint_test_data() - test_data_2 = TaskBlueprint_test_data() - trbt_test_data_1 = TaskRelationBlueprint_test_data() - trbt_test_data_2 = TaskRelationBlueprint_test_data() - task_blueprint = models.TaskBlueprint.objects.create(**test_data_1) - task_relation_blueprint_1 = models.TaskRelationBlueprint.objects.create(**trbt_test_data_1) - task_relation_blueprint_1.producer = task_blueprint - task_relation_blueprint_1.save() - task_relation_blueprint_2 = models.TaskRelationBlueprint.objects.create(**trbt_test_data_2) - task_relation_blueprint_2.consumer = task_blueprint - task_relation_blueprint_2.save() + task_blueprint = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data()) + task_relation_blueprint_1 = models.TaskRelationBlueprint.objects.create(**TaskRelationBlueprint_test_data(producer=task_blueprint)) + task_relation_blueprint_2 = models.TaskRelationBlueprint.objects.create(**TaskRelationBlueprint_test_data(consumer=task_blueprint)) + # assert response_data = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/%s/' % task_blueprint.id, 200) - assertUrlList(self, response_data['produced_by'], [task_relation_blueprint_1]) - assertUrlList(self, response_data['consumed_by'], [task_relation_blueprint_2]) + assertUrlList(self, response_data['consumed_by'], [task_relation_blueprint_1]) + assertUrlList(self, response_data['produced_by'], [task_relation_blueprint_2]) + + def test_TaskBlueprint_filters_for_SchedulingUnitBlueprint(self): + + # setup + su_blueprint_1 = models.SchedulingUnitBlueprint.objects.create(**SchedulingUnitBlueprint_test_data("sub_%s" % uuid.uuid4())) + su_blueprint_2 = models.SchedulingUnitBlueprint.objects.create(**SchedulingUnitBlueprint_test_data("sub_%s" % uuid.uuid4())) + su_blueprint_3 = models.SchedulingUnitBlueprint.objects.create(**SchedulingUnitBlueprint_test_data("sub_%s" % uuid.uuid4())) + task_blueprint_1 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data("tb_%s" % uuid.uuid4(), scheduling_unit_blueprint=su_blueprint_1)) + task_blueprint_2 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data("tb_%s" % uuid.uuid4(), scheduling_unit_blueprint=su_blueprint_2)) + task_blueprint_3 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data("tb_%s" % uuid.uuid4(), scheduling_unit_blueprint=su_blueprint_3)) + + # assert + response_1 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?scheduling_unit_blueprint=%s' % su_blueprint_1.id, 200) + response_2 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?scheduling_unit_blueprint=%s,%s' % (su_blueprint_2.id, su_blueprint_3.id), 200) + response_3 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?scheduling_unit_blueprint_min=%s&scheduling_unit_blueprint_max=%s' % (su_blueprint_3.id, su_blueprint_3.id), 200) + response_4 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?scheduling_unit_blueprint_name=%s' % su_blueprint_2.name[:-3], 200) + GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?scheduling_unit_blueprint=%s' % 99999, 400) + self.assertEqual(response_1['count'], 1) + self.assertIn(task_blueprint_1.name, str(response_1)) + self.assertEqual(response_2['count'], 2) + self.assertNotIn(task_blueprint_1.name, str(response_2)) + self.assertIn(task_blueprint_2.name, str(response_2)) + self.assertIn(task_blueprint_3.name, str(response_2)) + self.assertEqual(response_3['count'], 1) + self.assertNotIn(task_blueprint_1.name, str(response_3)) + self.assertNotIn(task_blueprint_2.name, str(response_3)) + self.assertIn(task_blueprint_3.name, str(response_3)) + self.assertEqual(response_4['count'], 1) + self.assertNotIn(task_blueprint_1.name, str(response_4)) + self.assertIn(task_blueprint_2.name, str(response_4)) + self.assertNotIn(task_blueprint_3.name, str(response_4)) + + def test_TaskBlueprint_filters_for_TaskDraft(self): + + # setup + task_draft_1 = models.TaskDraft.objects.create(**TaskDraft_test_data("td_%s" % uuid.uuid4())) + task_draft_2 = models.TaskDraft.objects.create(**TaskDraft_test_data("td_%s" % uuid.uuid4())) + task_draft_3 = models.TaskDraft.objects.create(**TaskDraft_test_data("td_%s" % uuid.uuid4())) + task_blueprint_1 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data(name="tb_%s" % uuid.uuid4(), task_draft=task_draft_1)) + task_blueprint_2 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data(name="tb_%s" % uuid.uuid4(), task_draft=task_draft_2)) + task_blueprint_3 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data(name="tb_%s" % uuid.uuid4(), task_draft=task_draft_3)) + + # assert + response_1 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?draft=%s' % task_draft_1.id, 200) + response_2 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?draft_min=%s&draft_max=%s' % (task_draft_2.id, task_draft_2.id), 200) + response_3 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?draft=%s,%s' % (task_draft_1.id, task_draft_3.id), 200) + GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?draft=%s' % 9999999, 400) + self.assertIn(task_blueprint_1.name, str(response_1)) + self.assertNotIn(task_blueprint_2.name, str(response_1)) + self.assertNotIn(task_blueprint_3.name, str(response_1)) + self.assertNotIn(task_blueprint_1.name, str(response_2)) + self.assertIn(task_blueprint_2.name, str(response_2)) + self.assertNotIn(task_blueprint_3.name, str(response_2)) + self.assertIn(task_blueprint_1.name, str(response_3)) + self.assertNotIn(task_blueprint_2.name, str(response_3)) + self.assertIn(task_blueprint_3.name, str(response_3)) + + def test_TaskBlueprint_filters_for_Subtask(self): + + # setup + task_blueprint_1 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data(name="tb_%s" % uuid.uuid4())) + task_blueprint_2 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data(name="tb_%s" % uuid.uuid4())) + task_blueprint_3 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data(name="tb_%s" % uuid.uuid4())) + subtask_1 = models.Subtask.objects.create(**Subtask_test_data()) + subtask_2 = models.Subtask.objects.create(**Subtask_test_data()) + subtask_3 = models.Subtask.objects.create(**Subtask_test_data()) + subtask_1.task_blueprints.set([task_blueprint_1]) + subtask_2.task_blueprints.set([task_blueprint_2]) + subtask_3.task_blueprints.set([task_blueprint_3]) + subtask_1.save() + subtask_2.save() + subtask_3.save() + + # assert + response_1 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?subtasks=%s' % subtask_1.id, 200) + response_2 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?subtasks_min=%s&subtasks_max=%s' % (subtask_2.id, subtask_2.id), 200) + response_3 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?subtasks=%s&subtasks=%s' % (subtask_1.id, subtask_3.id), 200) + GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?subtasks=%s' % 9999999, 400) + self.assertIn(task_blueprint_1.name, str(response_1)) + self.assertNotIn(task_blueprint_2.name, str(response_1)) + self.assertNotIn(task_blueprint_3.name, str(response_1)) + self.assertNotIn(task_blueprint_1.name, str(response_2)) + self.assertIn(task_blueprint_2.name, str(response_2)) + self.assertNotIn(task_blueprint_3.name, str(response_2)) + self.assertIn(task_blueprint_1.name, str(response_3)) + self.assertNotIn(task_blueprint_2.name, str(response_3)) + self.assertIn(task_blueprint_3.name, str(response_3)) + + def test_TaskBlueprint_filters_for_status(self): + + # setup + task_blueprint_1 = models.TaskBlueprint.objects.create(**TaskBlueprint_test_data(name="tb_%s" % uuid.uuid4())) + + # assert + response_1 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?status=defined', 200) + response_2 = GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?status=obsolete', 200) + GET_and_assert_equal_expected_code(self, BASE_URL + '/task_blueprint/?status=gibberish', 400) + self.assertGreater(response_1['count'], 0) + self.assertEqual(response_2['count'], 0) class TaskRelationBlueprintTestCase(unittest.TestCase): diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js b/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js index 9ad010ccc1f834962e1570aac3da41599991a50a..129b8232bf12d6353bc1507d27f1b17a1821b683 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js @@ -761,6 +761,10 @@ function FlatpickrRangeColumnFilter({ if (storeFilter) { const filter = TableUtil.getFilter(currentTableName, Header); const filterValue = _.map(filter, date => {return new Date(date)} ) + if (filter === '') { + TableUtil.saveFilter(currentTableName, Header, [] ); + setFilter(undefined); + } if (filterValue[1] && !value ){ setValue(filterValue); setFilter(filterValue); @@ -779,6 +783,11 @@ function FlatpickrRangeColumnFilter({ if(filterColumn) { filterColumn.value = value; filterCallback(tableOptionsState, setLoaderFunction); + } else if (!filterColumn && value && value.length === 2) { + // Here the above condition placed because the Start/End time filters is not consistency in tableOptionsState.filters + filterColumn = {id: Header, value: value} + tableOptionsState.filters.push(filterColumn); + filterCallback(tableOptionsState, setLoaderFunction); } else { filterCallback(tableOptionsState, setLoaderFunction); } @@ -820,7 +829,7 @@ function FlatpickrRangeColumnFilter({ </button> <button class="p-button p-component p-button-icon-only calendar-reset" onClick={(value) => { - setFilter(undefined); setValue([]); setFiltered(false); + setFilter(undefined); setValue([]); setFiltered(false);filterValue = []; if(storeFilter){ TableUtil.saveFilter(currentTableName, Header, [] ); } @@ -1279,7 +1288,7 @@ function NumberRangeFilter({ function RankRangeFilter({ column: { filterValue = [], preFilteredRows, setFilter, id, Header }, }) { - let [rangeValue, setRangeValue] = useState([0,0]); + let [rangeValue, setRangeValue] = useState([]); const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); React.useEffect(() => { @@ -1457,7 +1466,7 @@ function DurationRangeFilter({ <InputMask mask="99:99:99" value={value[0]} placeholder="HH:mm:ss" - tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Minimum Range value and press ‘Enter’ key to search"} + tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Minimum Range value in HH:mm:ss format and press ‘Enter’ key to search"} onChange={e => { setFilter(undefined); setFiltered(false); let val = e.target.value; @@ -1482,7 +1491,7 @@ function DurationRangeFilter({ <InputMask mask="99:99:99" value={value[1]} - tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Maximum Range value and press ‘Enter’ key to search"} + tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Maximum Range value in HH:mm:ss format and press ‘Enter’ key to search"} placeholder="HH:mm:ss" onChange={e => { setFilter(undefined); setFiltered(false); @@ -1499,13 +1508,12 @@ function DurationRangeFilter({ //TableUtil.saveFilter(currentTableName, Header, [min,val]); setFilter([min,val]); } - }} - style={{ - width: '85px', - height: '25px' - }} + }} + style={{ + width: '85px', + height: '25px' + }} /> - </div> ) diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js index 4fe8c56472efb434592484fe524792fc81cb9075..990c1afc455317df16cbb52108fedb0fa2825449 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/SchedulingUnitList.js @@ -1141,25 +1141,22 @@ class SchedulingUnitList extends Component{ if(filters.length > 0 ) { for( const filter of filters) { if (filter.id === 'Start Time') { - //this.filterQry += 'start_time_after='+filter.value+'&start_time_before='+_.replace(filter.value, '00:00:00', '23:59:59')+'&'; const values = _.split(filter.value, ","); if (values.length>2){ continue; } if((values[0] && values[0] != '' && values[0] != 'null') && (values[1] && values[1] != '' && values[1] != 'null')) { - this.filterQry += 'start_time_after='+values[0]+'&'; - this.filterQry += 'start_time_before='+_.replace(values[1], '00:00:00', '23:59:59')+'&'; + this.filterQry += 'start_time_after='+ moment(new Date(values[0])).format("YYYY-MM-DDT00:00:00")+".000Z&"; + this.filterQry += 'start_time_before='+moment(new Date(values[1])).format("YYYY-MM-DDT23:59:59")+".000Z&"; } } else if (filter.id === 'End Time') { - //this.filterQry += 'stop_time_after='+filter.value+'&stop_time_before='+_.replace(filter.value, '00:00:00', '23:59:59')+'&' - //filter.value = _.replace(filter.value, '00:00:00', '23:59:59'); const values = _.split(filter.value, ","); if (values.length>2){ continue; } if((values[0] && values[0] != '' && values[0] != 'null') && (values[1] && values[1] != '' && values[1] != 'null')) { - this.filterQry += 'stop_time_after='+values[0]+'&'; - this.filterQry += 'stop_time_before='+_.replace(values[1], '00:00:00', '23:59:59')+'&'; + this.filterQry += 'stop_time_after='+ moment(new Date(values[0])).format("YYYY-MM-DDT00:00:00")+".000Z&"; + this.filterQry += 'stop_time_before='+moment(new Date(values[1])).format("YYYY-MM-DDT23:59:59")+".000Z&"; } } else if ((filter.id === 'Scheduling Unit ID' || filter.id === 'Linked Draft ID') && filter.value != '') { let columnDetails = _.find(this.state.columnMap, {displayName:filter.id}); @@ -1185,8 +1182,8 @@ class SchedulingUnitList extends Component{ continue; } if((values[0] && values[0] != '' && values[0] != 'null') && (values[1] && values[1] != '' && values[1] != 'null')) { - this.filterQry += columnDetails.orgField+'_after='+values[0]+'&'; - this.filterQry += columnDetails.orgField+'_before='+_.replace(values[1], '00:00:00', '23:59:59')+'&'; + this.filterQry += columnDetails.orgField+'_after='+ moment(new Date(values[0])).format("YYYY-MM-DDT00:00:00")+".000Z&"; + this.filterQry += columnDetails.orgField+'_before='+moment(new Date(values[1])).format("YYYY-MM-DDT23:59:59")+".000Z&"; } } else if (filter.id === 'Duration (HH:mm:ss)' && filter.value != '') { let columnDetails = _.find(this.state.columnMap, {displayName:filter.id}); diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js index fab924a2355fb6d4e865b32471e91f288457d761..521de333fb73efe8270b8aabf42c01e90d8226ea 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js @@ -158,6 +158,7 @@ class ViewSchedulingUnit extends Component { taskStatus: [], userPermission: {permissions: AuthStore.getState().userRolePermission} } + this.statusList = []; this.access_denied_message = "Don't have permission"; this.actions = []; this.stations = []; @@ -202,6 +203,7 @@ class ViewSchedulingUnit extends Component { this.getCleanUpDialogContent = this.getCleanUpDialogContent.bind(this); this.cleanUpSUTask = this.cleanUpSUTask.bind(this); this.confirmAutoDeletion = this.confirmAutoDeletion.bind(this); + this.getFilterOptions = this.getFilterOptions.bind(this); } componentDidUpdate(prevProps, prevState) { @@ -216,7 +218,33 @@ class ViewSchedulingUnit extends Component { this.setState({ showTaskRelationDialog: !this.state.showTaskRelationDialog }); } + /** + * Get Status list for UI drop downl + */ + async getStatusList() { + const taskFilters = await TaskService.getTaskFilterDefinition('blueprint'); + if (taskFilters && taskFilters.data.filters['status']) { + taskFilters.data.filters['status'].choices.forEach(choice => { + this.statusList.push(choice.value); + }) + } + } + + /** + * Get Option-list values for Select Dropdown filter in 'Viewtable' + * @param {String} id : Column id + * @returns + */ + getFilterOptions(id) { + let options = null; + if(id && id === 'Status') { + options = this.statusList; + } + return options; + } + async componentDidMount() { + this.getStatusList(); let permission = (await AuthUtil.getUserRolePermission()); permission = { permissions: permission.userRolePermission}; this.pageUpdated = true; @@ -1409,6 +1437,7 @@ class ViewSchedulingUnit extends Component { optionalcolumns={this.state.optionalcolumns} columnclassname={this.state.columnclassname} columnOrders={this.state.columnOrders} + showFilterOption={this.getFilterOptions} //Callback function to provide inputs for option-list in Select Dropdown filter showaction="true" keyaccessor="id" paths={this.state.paths} diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/list.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/list.js index dca1323ec5d92212520c6f3aa6c54047eb856d8b..580724bf427183a33697b1450dc0cdd573975664 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/list.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/list.js @@ -28,6 +28,8 @@ export class TaskList extends Component { TASK_END_STATUSES = ['finished', 'error', 'cancelled']; TASK_DRAFT_EXPAND = 'task_blueprints,task_blueprints.subtasks,scheduling_unit_draft,scheduling_unit_draft.scheduling_set'; TASK_BLUEPRINT_EXPAND = 'subtasks,subtasks.output_dataproducts,draft,scheduling_unit_blueprint,draft.scheduling_unit_draft,draft.scheduling_unit_draft.scheduling_set'; + COMMA_SEPARATE_TOOLTIP ='Enter Id and press ‘Enter’ key to search. For multiple values enter comma separated values. For range, provide input like 1..6'; + constructor(props) { super(props); this.getUIAttr(); @@ -77,10 +79,12 @@ export class TaskList extends Component { filter: "select" }, scheduling_unit_draft: { - name:"Scheduling Unit ID" + name:"Scheduling Unit ID", + tooltip: this.COMMA_SEPARATE_TOOLTIP }, scheduling_unit_blueprint: { - name:"Scheduling Unit ID" + name:"Scheduling Unit ID", + tooltip: this.COMMA_SEPARATE_TOOLTIP }, schedulingUnitName: { name:"Scheduling Unit Name" @@ -89,10 +93,12 @@ export class TaskList extends Component { name: "Project" }, id: { - name:"ID" + name:"ID", + tooltip: this.COMMA_SEPARATE_TOOLTIP }, subTaskID: { - name:"Control ID" + name:"Control ID", + tooltip: this.COMMA_SEPARATE_TOOLTIP }, name: { name:"Name" @@ -102,22 +108,25 @@ export class TaskList extends Component { }, start_time: { name: "Start Time", - filter: "date", + filter: "flatpickrDateRange", format: UIConstants.CALENDAR_DATETIME_FORMAT }, stop_time: { name: "End Time", - filter: "date", + filter: "flatpickrDateRange", format: UIConstants.CALENDAR_DATETIME_FORMAT }, duration: { - name:"Duration (HH:mm:ss)" + name:"Duration (HH:mm:ss)", + filter: "durationMinMax", }, relative_start_time: { - name:"Relative Start Time (HH:mm:ss)" + name:"Relative Start Time (HH:mm:ss)", + filter: "durationMinMax", }, relative_stop_time: { - name:"Relative End Time (HH:mm:ss)" + name:"Relative End Time (HH:mm:ss)", + filter: "durationMinMax", }, noOfOutputProducts: { name:"#Dataproducts" @@ -141,19 +150,20 @@ export class TaskList extends Component { name:"Tags" }, draft: { - name:"Linked Draft ID" + name:"Linked Draft ID", + tooltip: this.COMMA_SEPARATE_TOOLTIP }, url: { name:"API URL" }, created_at: { name: "Created at", - filter: "date", + filter: "flatpickrDateRange", format: UIConstants.CALENDAR_DATETIME_FORMAT }, updated_at: { name: "Updated at", - filter: "date", + filter: "flatpickrDateRange", format: UIConstants.CALENDAR_DATETIME_FORMAT }, actionpath: "actionpath" @@ -169,7 +179,7 @@ export class TaskList extends Component { "Cancelled": "filter-input-50", "Duration (HH:mm:ss)": "filter-input-75", "Template ID": "filter-input-50", - "Linked Draft ID": "filter-input-50", + "Linked Draft ID": "filter-input-75", "Relative Start Time (HH:mm:ss)": "filter-input-75", "Relative End Time (HH:mm:ss)": "filter-input-75", "Start Time": "filter-input-150", @@ -179,11 +189,14 @@ export class TaskList extends Component { "Data size": "filter-input-50", "Data size on Disk": "filter-input-50", "Subtask Content": "filter-input-75", - "Linked BluePrint ID": "filter-input-50", - "API URL":"filter-input-175" + "Linked BluePrint ID": "filter-input-75", + "API URL":"filter-input-175", + "Created at":"filter-input-150", + "Updated at":"filter-input-150", }], actions: [] }; + this.statusList = []; this.access_denied_message = "Don't have permission"; this.pageUpdated = true; this.taskTypeList = [{name: 'Blueprint'}, {name: 'Draft'}]; @@ -206,6 +219,7 @@ export class TaskList extends Component { this.getTaskCancelStatusContent = this.getTaskCancelStatusContent.bind(this); this.changeTaskType = this.changeTaskType.bind(this); this.fetchTableData = this.fetchTableData.bind(this); + this.getFilterOptions = this.getFilterOptions.bind(this); } subtaskComponent = (task) => { @@ -624,12 +638,25 @@ export class TaskList extends Component { tmpDefaulColumns = _.omit(tmpDefaulColumns,columnDefinitionToRemove); tmpOptionalColumns = _.omit(tmpOptionalColumns,columnDefinitionToRemove); if(taskFilters) { + this.getStatusList(taskFilters); tmpDefaulColumns = this.getAPIFilter(taskFilters, tmpDefaulColumns); tmpOptionalColumns = this.getAPIFilter(taskFilters, tmpOptionalColumns); await this.setState({tmpDefaulcolumns: [tmpDefaulColumns], tmpOptionalcolumns:[tmpOptionalColumns], tmpColumnOrders: tmpColumnOrders, columnMap: this.columnMap}) } } + /** + * Get Status list frol filter + * @param {Array} suFilters + */ + getStatusList(taskFilters) { + if (taskFilters.data.filters['status']) { + taskFilters.data.filters['status'].choices.forEach(choice => { + this.statusList.push(choice.value); + }) + } + } + getAPIFilter(taskFilters, columnDef) { const defaultColKeys = Object.keys(columnDef); defaultColKeys.forEach(key => { @@ -646,11 +673,35 @@ export class TaskList extends Component { columnDef[key]['disableSortBy'] = !_.includes(taskFilters.data.ordering, tempKey); columnDef[key]['disableFilters'] = false; if(UIConstants.FILTER_MAP[taskFilters.data.filters[tempKey].type]) { - if (tempKey === 'draft') { //this condition because to avoid dropdown filter for 'Linked Draft ID' + /*if (tempKey === 'draft') { //this condition because to avoid dropdown filter for 'Linked Draft ID' taskFilters.data.filters[tempKey].type = 'CharFilter'; - } + }*/ columnDef[key]['filter'] = UIConstants.FILTER_MAP[taskFilters.data.filters[tempKey].type]; } + } else if (key === 'subTaskID' && taskFilters.data.filters['subtasks']) { + columnDef[key]['disableSortBy'] = !_.includes(taskFilters.data.ordering, 'subtasks'); + columnDef[key]['disableFilters'] = false; + } else if (tempKey === 'schedulingUnitName' && + (taskFilters.data.filters['scheduling_unit_draft_name'] || taskFilters.data.filters['scheduling_unit_blueprint_name'])) { + if (this.state.taskType === 'Draft') { + columnDef[key]['disableSortBy'] = !_.includes(taskFilters.data.ordering, 'scheduling_unit_draft_name'); + columnDef[key]['disableFilters'] = false; + } else { + columnDef[key]['disableSortBy'] = !_.includes(taskFilters.data.ordering, 'scheduling_unit_blueprint_name'); + columnDef[key]['disableFilters'] = false; + } + } else if (key === 'duration' && taskFilters.data.filters['duration_min']) { + columnDef[key]['disableSortBy'] = !_.includes(taskFilters.data.ordering, 'duration_min'); + columnDef[key]['disableFilters'] = false; + } else if (key === 'relative_start_time' && taskFilters.data.filters['relative_start_time_min']) { + columnDef[key]['disableSortBy'] = !_.includes(taskFilters.data.ordering, 'relative_start_time_min'); + columnDef[key]['disableFilters'] = false; + } else if (key === 'relative_stop_time' && taskFilters.data.filters['relative_stop_time_min']) { + columnDef[key]['disableSortBy'] = !_.includes(taskFilters.data.ordering, 'relative_stop_time_min'); + columnDef[key]['disableFilters'] = false; + } else if (key === 'draft' && taskFilters.data.filters['task_blueprints']) { + columnDef[key]['disableSortBy'] = !_.includes(taskFilters.data.ordering, 'task_blueprints'); + columnDef[key]['disableFilters'] = false; } else if (columnDef[key]['name']) { columnDef[key]['disableSortBy'] = true; columnDef[key]['disableFilters'] = true; @@ -732,13 +783,70 @@ export class TaskList extends Component { if(filters.length > 0 ) { for( const filter of filters) { if (filter.id === 'Start Time') { - this.filterQry += 'start_time_after='+filter.value+'&start_time_before='+_.replace(filter.value, '00:00:00', '23:59:59')+'&'; + const values = _.split(filter.value, ","); + if (values.length>2){ + continue; + } + if((values[0] && values[0] != '' && values[0] != 'null') && (values[1] && values[1] != '' && values[1] != 'null')) { + this.filterQry += 'start_time_after='+ moment(new Date(values[0])).format("YYYY-MM-DDT00:00:00")+".000Z&"; + this.filterQry += 'start_time_before='+moment(new Date(values[1])).format("YYYY-MM-DDT23:59:59")+".000Z&"; + } } else if (filter.id === 'End Time') { - this.filterQry += 'stop_time_after='+filter.value+'&stop_time_before='+_.replace(filter.value, '00:00:00', '23:59:59')+'&' - } else { + const values = _.split(filter.value, ","); + if (values.length>2){ + continue; + } + if((values[0] && values[0] != '' && values[0] != 'null') && (values[1] && values[1] != '' && values[1] != 'null')) { + this.filterQry += 'stop_time_after='+ moment(new Date(values[0])).format("YYYY-MM-DDT00:00:00")+".000Z&"; + this.filterQry += 'stop_time_before='+moment(new Date(values[1])).format("YYYY-MM-DDT23:59:59")+".000Z&"; + } + } else if (filter.id === 'Scheduling Unit Name') { + if (this.state.taskType === 'Draft') { + this.filterQry += 'scheduling_unit_draft_name='+filter.value+'&'; + } else { + this.filterQry += 'scheduling_unit_blueprint_name='+filter.value+'&'; + } + } else if ((filter.id === 'Duration (HH:mm:ss)' || filter.id === 'Relative Start Time (HH:mm:ss)' || filter.id === 'Relative End Time (HH:mm:ss)') && filter.value != '') { + let columnDetails = _.find(this.state.columnMap, {displayName:filter.id}); + const values = _.split(filter.value, ","); + if (values[0].includes(":")) { + this.filterQry += columnDetails.orgField+"_min" +'=PT'+UnitConverter.getHHmmssToSecs(values[0])+'S&'; + } + if (values[1].includes(":")) { + this.filterQry += columnDetails.orgField+"_max" +'=PT'+UnitConverter.getHHmmssToSecs(values[1])+'S&'; + } + } else if (filter.id === 'Linked Blueprint ID' && filter.value != '') { + const values = UnitConverter.getSubbandOutput(filter.value) + _.split(values, ",").forEach(value =>{ + if(value && _.trim(value) !== '') { + this.filterQry += 'task_blueprints='+_.trim(value)+'&'; + } + }); + } else if ((filter.id === 'Created at' || filter.id === 'Updated at') && filter.value != '') { + let columnDetails = _.find(this.state.columnMap, {displayName:filter.id}); + const values = _.split(filter.value, ","); + if (values.length>2){ + continue; + } + if((values[0] && values[0] != '' && values[0] != 'null') && (values[1] && values[1] != '' && values[1] != 'null')) { + this.filterQry += columnDetails.orgField+'_after='+ moment(new Date(values[0])).format("YYYY-MM-DDT00:00:00")+".000Z&"; + this.filterQry += columnDetails.orgField+'_before='+moment(new Date(values[1])).format("YYYY-MM-DDT23:59:59")+".000Z&"; + } + } else if ((filter.id === 'Control ID') && filter.value != '') { + const values = UnitConverter.getSubbandOutput(filter.value); + _.split(values, ",").forEach(value =>{ + if(value && _.trim(value) !== '') { + this.filterQry += 'subtasks='+_.trim(value)+'&'; + } + }); + } else if ((filter.id === 'Scheduling Unit ID' || filter.id === 'Linked Draft ID'|| filter.id === 'ID') && filter.value != '') { + let columnDetails = _.find(this.state.columnMap, {displayName:filter.id}); + const values = UnitConverter.getSubbandOutput(filter.value); + this.filterQry += columnDetails.orgField+'='+values.toString()+"&"; + } else { let columnDetails = _.find(this.state.columnMap, {displayName:filter.id}); if(columnDetails) { - this.filterQry += columnDetails.orgField +'='+filter.value+'&' + this.filterQry += columnDetails.orgField +'='+_.trim(filter.value)+'&' } } } @@ -757,6 +865,19 @@ export class TaskList extends Component { return [this.state.tasks, this.totalPage]; } + /** + * Get Option-list values for Select Dropdown filter in 'Viewtable' + * @param {String} id : Column id + * @returns + */ + getFilterOptions(id) { + let options = null; + if(id && id === 'Status') { + options = this.statusList; + } + return options; + } + render() { if (this.state.redirect) { return <Redirect to={{ pathname: this.state.redirect }}></Redirect> @@ -795,6 +916,7 @@ export class TaskList extends Component { columnclassname={this.state.columnclassname} columnOrders={this.state.tmpColumnOrders} defaultSortColumn={this.defaultSortColumn} + showFilterOption={this.getFilterOptions} //Callback function to provide inputs for option-list in Select Dropdown filter showaction="true" keyaccessor="id" paths={this.state.paths} diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js index 81be74c071bcab3fd94a3bde47ef10948ee35229..08f084530c8cdcb7a6281b004da1eeef74aeeec0 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Task/view.js @@ -228,12 +228,12 @@ export class TaskView extends Component { let task = this.state.task; let cancelledTask = await TaskService.cancelTask(task.id); if (!cancelledTask) { - appGrowl.show({ severity: 'error', summary: 'error', detail: 'Error while cancelling Scheduling Unit' }); + appGrowl.show({ severity: 'error', summary: 'error', detail: 'Error while cancelling Task' }); this.setState({ dialogVisible: false }); } else { task.status = cancelledTask.status; let actions = this.state.actions; - appGrowl.show({ severity: 'success', summary: 'Success', detail: 'Scheduling Unit is cancelled successfully' }); + appGrowl.show({ severity: 'success', summary: 'Success', detail: 'Task is cancelled successfully' }); this.setState({ confirmDialogVisible: false, task: task, actions: actions}); } } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/list.tabs.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/list.tabs.js index cebe73f0aa5a71237abdfb3cc7cc2fad0b557cfd..1d6b270679205a88a36a258e980942d7e49b2fbd 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/list.tabs.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/list.tabs.js @@ -28,6 +28,8 @@ class TimelineListTabs extends Component { this.suListFilterCallback = this.suListFilterCallback.bind(this); this.taskListFilterCallback = this.taskListFilterCallback.bind(this); this.getTaskList = this.getTaskList.bind(this); + this.getSUFilterOptions = this.getSUFilterOptions.bind(this); + this.getTaskFilterOptions = this.getTaskFilterOptions.bind(this); } /** @@ -121,6 +123,32 @@ class TimelineListTabs extends Component { return sortData?[{...sortData}]:[this.defaultSortColumns[listName]]; } + /** + * Get Option-list values for Select Dropdown filter in SU 'Viewtable' + * @param {String} id : Column id + * @returns + */ + getSUFilterOptions(id) { + let options = null; + if(id && id === 'Status') { + options = this.props.suStatusList; + } + return options; + } + + /** + * Get Option-list values for Select Dropdown filter in Task 'Viewtable' + * @param {String} id : Column id + * @returns + */ + getTaskFilterOptions(id) { + let options = null; + if(id && id === 'Status') { + options = this.props.taskStatusList; + } + return options; + } + render() { const taskList = this.getTaskList(); return( @@ -137,6 +165,7 @@ class TimelineListTabs extends Component { defaultSortColumn={this.getSortingColumn("SUListSortColumn")} showaction="true" tablename={`timeline_scheduleunit_list`} + showFilterOption={this.getSUFilterOptions} //Callback function to provide inputs for option-list in Select Dropdown filter showTopTotal={false} showGlobalFilter={true} showColumnFilter={true} @@ -159,6 +188,7 @@ class TimelineListTabs extends Component { showGlobalFilter={true} showColumnFilter={true} tablename={`timeline_task_list`} + showFilterOption={this.getTaskFilterOptions} //Callback function to provide inputs for option-list in Select Dropdown filter showTopTotal={false} filterCallback={this.taskListFilterCallback} lsKeySortColumn={"TaskListSortColumn"} diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js index dcb6ff2d3f8ed5d02224005f2c967f762dd75270..1faf0cf5704099a5f8114ad5884b45fd9680a530 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js @@ -88,7 +88,9 @@ export class TimelineView extends Component { selectedTaskTypes: this.timelineUIAttributes["taskTypes"] || ['observation'], isStationTasksVisible: this.timelineUIAttributes.isStationTasksVisible===undefined?true:this.timelineUIAttributes.isStationTasksVisible, showReservation: this.timelineUIAttributes.showReservation || false, // Flag to show reservations in normal timeline view - userrole: AuthStore.getState() + userrole: AuthStore.getState(), + suStatusList: [], + taskStatusList: [] } this.STATUS_BEFORE_SCHEDULED = ['defining', 'defined', 'schedulable']; // Statuses before scheduled to get station_group this.allStationsGroup = []; @@ -124,6 +126,7 @@ export class TimelineView extends Component { } async componentDidMount() { + this.getStatusList(); const permission = await AuthUtil.getUserRolePermission(); const timelinePermission = permission.userRolePermission.timeline; @@ -1075,6 +1078,27 @@ export class TimelineView extends Component { this.setState({showReservation: !this.state.showReservation}); } + /** + * Get Status list for UI drop down list + */ + async getStatusList() { + let suStatusList = []; + let taskStatusList = []; + const suFilters = await ScheduleService.getSchedulingUnitFilterDefinition('blueprint'); + if (suFilters && suFilters.data.filters['status']) { + suFilters.data.filters['status'].choices.forEach(choice => { + suStatusList.push(choice.value); + }); + } + const taskFilters = await TaskService.getTaskFilterDefinition('blueprint'); + if (taskFilters && taskFilters.data.filters['status']) { + taskFilters.data.filters['status'].choices.forEach(choice => { + taskStatusList.push(choice.value); + }); + } + this.setState({suStatusList: suStatusList, taskStatusList: taskStatusList}); + } + render() { if (this.state.redirect) { return <Redirect to={{ pathname: this.state.redirect }}></Redirect> @@ -1117,7 +1141,10 @@ export class TimelineView extends Component { style={isSUListVisible ? { position: "inherit", borderRight: "3px solid #efefef", paddingTop: "10px" } : { display: 'none' }}> <TimelineListTabs suBlueprintList={this.state.suBlueprintList} suListFilterCallback={this.suListFilterCallback} - reservationList={this.getReservationList()}></TimelineListTabs> + reservationList={this.getReservationList()} + suStatusList={this.state.suStatusList} + taskStatusList={this.state.taskStatusList} + ></TimelineListTabs> </div> {/* Timeline Panel */} <div className={isSUListVisible ? ((isSUDetsVisible || isReservDetsVisible) ? "col-lg-5 col-md-5 col-sm-12" : diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js index 53d12803f8d8edc4d73f6a1c99b181b1b1ebc8b5..e07a63a57a083c1fb822e049d0d5d23689b7eee2 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js @@ -12,6 +12,7 @@ import PageHeader from '../../layout/components/PageHeader'; import Timeline from '../../components/Timeline'; import ScheduleService from '../../services/schedule.service'; +import TaskService from '../../services/task.service'; import UtilService from '../../services/util.service'; import UnitConverter from '../../utils/unit.converter'; @@ -64,7 +65,9 @@ export class WeekTimelineView extends Component { suTaskList: [], isSummaryLoading: false, stationGroup: [], - reservationEnabled: true + reservationEnabled: true, + suStatusList: [], + taskStatusList: [] } this.STATUS_BEFORE_SCHEDULED = ['defining', 'defined', 'schedulable']; // Statuses before scheduled to get station_group this.reservations = []; @@ -89,6 +92,7 @@ export class WeekTimelineView extends Component { } async componentDidMount() { + this.getStatusList(); const permission = await AuthUtil.getUserRolePermission(); const weekviewPermission = permission.userRolePermission.weekoverview; let menuOptions = [{ label: 'Add Reservation', icon: "fa fa-", disabled: !weekviewPermission.addreservation, command: () => { this.selectOptionMenu('Add Reservation') } }, @@ -801,6 +805,27 @@ export class WeekTimelineView extends Component { this.timeline.updateTimeline(updatedItemGroupData); } + /** + * Get Status list for UI drop down list + */ + async getStatusList() { + let suStatusList = []; + let taskStatusList = []; + const suFilters = await ScheduleService.getSchedulingUnitFilterDefinition('blueprint'); + if (suFilters && suFilters.data.filters['status']) { + suFilters.data.filters['status'].choices.forEach(choice => { + suStatusList.push(choice.value); + }); + } + const taskFilters = await TaskService.getTaskFilterDefinition('blueprint'); + if (taskFilters && taskFilters.data.filters['status']) { + taskFilters.data.filters['status'].choices.forEach(choice => { + taskStatusList.push(choice.value); + }); + } + this.setState({suStatusList: suStatusList, taskStatusList: taskStatusList}); + } + render() { if (this.state.redirect) { return <Redirect to={{ pathname: this.state.redirect }}></Redirect> @@ -845,6 +870,8 @@ export class WeekTimelineView extends Component { <TimelineListTabs suBlueprintList={this.state.suBlueprintList} suListFilterCallback={this.suListFilterCallback} reservationList={this.getReservationList()} + suStatusList={this.state.suStatusList} + taskStatusList={this.state.taskStatusList} ></TimelineListTabs> </div> {/* Timeline Panel */} diff --git a/SAS/TMSS/frontend/tmss_webapp/src/shared/timeline.constants.js b/SAS/TMSS/frontend/tmss_webapp/src/shared/timeline.constants.js index c588cbafccdc976da6fd44d642e68aed61e54738..65d51fe61b2805b6ef729f418282f41f35309a06 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/shared/timeline.constants.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/shared/timeline.constants.js @@ -3,7 +3,8 @@ import UIConstants from "../utils/ui.constants"; const TimelineConstants = { SU_LIST_DEFAULT_COLUMNS: [{ status: { - name:"Status" + name:"Status", + filter: "select", }, do_cancel: { name:"Cancelled" @@ -81,7 +82,7 @@ const TimelineConstants = { }], TASK_LIST_DEFAULT_COLUMNS: [{ status: { - name: "Status" + name: "Status", filter: "select" }, do_cancel: { name: "Cancelled" diff --git a/SAS/TMSS/frontend/tmss_webapp/src/utils/unit.converter.js b/SAS/TMSS/frontend/tmss_webapp/src/utils/unit.converter.js index 90814bc8d0c52f6a11898a8ecf22741e83e3d2f6..a5f59b0b9d6fec5aaeb89b36e1addaccb6b27205 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/utils/unit.converter.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/utils/unit.converter.js @@ -237,24 +237,6 @@ const UnitConverter = { } return radian; }, - /** - * Convert the string input for subband list to Array - * @param {String} prpOutput - */ - getSubbandOutput(prpOutput) { - const subbandArray = prpOutput ? prpOutput.split(",") : []; - let subbandList = []; - for (const subband of subbandArray) { - const subbandRange = subband.split('..'); - if (subbandRange.length > 1) { - subbandList = subbandList.concat(_.range(subbandRange[0], (parseInt(subbandRange[1]) + 1))); - } else if (subbandRange[0] !== ''){ - subbandList = subbandList.concat(parseInt(subbandRange[0])); - } - } - prpOutput = subbandList; - return prpOutput; - }, getStatusList(suFilters) { let statusList = []; if (suFilters.data.filters['status']) { @@ -263,7 +245,25 @@ const UnitConverter = { }); } return statusList; - } + }, + /** + * Convert the string input for subband list to Array + * @param {String} prpOutput + */ + getSubbandOutput(prpOutput) { + const subbandArray = prpOutput ? prpOutput.split(",") : []; + let subbandList = []; + for (const subband of subbandArray) { + const subbandRange = subband.split('..'); + if (subbandRange.length > 1) { + subbandList = subbandList.concat(_.range(subbandRange[0], (parseInt(subbandRange[1]) + 1))); + } else if (subbandRange[0] !== ''){ + subbandList = subbandList.concat(parseInt(subbandRange[0])); + } + } + prpOutput = subbandList; + return prpOutput; + } }; export default UnitConverter; \ No newline at end of file