Kea2-python 0.3.1__py3-none-any.whl → 0.3.2__py3-none-any.whl

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.

Potentially problematic release.


This version of Kea2-python might be problematic. Click here for more details.

@@ -553,6 +553,25 @@
553
553
  transform: scale(1.2);
554
554
  text-shadow: 0 0 5px rgba(0,0,0,0.6);
555
555
  }
556
+
557
+ /* Specific column widths for property violations table */
558
+ .table-violations th:nth-child(1), .table-violations td:nth-child(1) { /* Index */
559
+ width: 10%;
560
+ min-width: 60px;
561
+ text-align: center;
562
+ }
563
+
564
+ .table-violations th:nth-child(2), .table-violations td:nth-child(2) { /* Property Name */
565
+ width: 40%;
566
+ min-width: 200px;
567
+ text-align: left;
568
+ }
569
+
570
+ .table-violations th:nth-child(3), .table-violations td:nth-child(3) { /* Interaction Scenario Pages */
571
+ width: 50%;
572
+ min-width: 150px;
573
+ text-align: center;
574
+ }
556
575
 
557
576
  @media (max-width: 768px) {
558
577
  .container {
@@ -820,6 +839,117 @@
820
839
  border-color: #d1d5db;
821
840
  }
822
841
 
842
+ /* Property search container with outline */
843
+ .property-search-container {
844
+ position: relative;
845
+ display: flex;
846
+ align-items: center;
847
+ border: 1px solid #d1d5db;
848
+ border-radius: 6px;
849
+ background-color: #f8f9fa;
850
+ transition: all 0.2s ease;
851
+ overflow: hidden;
852
+ }
853
+
854
+ .property-search-container:hover {
855
+ border-color: #9ca3af;
856
+ }
857
+
858
+ .property-search-container:focus-within {
859
+ border-color: #3b82f6;
860
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
861
+ background-color: #ffffff;
862
+ }
863
+
864
+ /* Simple search input styling for Property Statistics */
865
+ .property-stats-search-simple {
866
+ border: none !important;
867
+ box-shadow: none !important;
868
+ background-color: transparent !important;
869
+ border-radius: 0 !important;
870
+ padding: 8px 12px !important;
871
+ font-size: 14px;
872
+ flex: 1;
873
+ outline: none;
874
+ }
875
+
876
+ .property-stats-search-simple:focus {
877
+ background-color: transparent !important;
878
+ box-shadow: none !important;
879
+ border: none !important;
880
+ outline: none;
881
+ }
882
+
883
+ .property-stats-search-simple::placeholder {
884
+ color: #9ca3af;
885
+ font-style: italic;
886
+ }
887
+
888
+ /* Search icon button */
889
+ .property-search-icon-btn {
890
+ background: none;
891
+ border: none;
892
+ padding: 8px 12px;
893
+ color: #6b7280;
894
+ cursor: pointer;
895
+ display: flex;
896
+ align-items: center;
897
+ justify-content: center;
898
+ transition: color 0.2s ease;
899
+ border-left: 1px solid #e5e7eb;
900
+ }
901
+
902
+ .property-search-icon-btn:hover {
903
+ color: #3b82f6;
904
+ background-color: rgba(59, 130, 246, 0.05);
905
+ }
906
+
907
+ .property-search-icon-btn:active {
908
+ color: #1d4ed8;
909
+ }
910
+
911
+ /* Activities Coverage table styling */
912
+ .table-activities thead {
913
+ background-color: #007bff !important;
914
+ color: white;
915
+ }
916
+
917
+ .table-activities .sort-icon {
918
+ color: #ffffff !important;
919
+ text-shadow: 0 0 3px rgba(0,0,0,0.4);
920
+ }
921
+
922
+ .table-activities .sort-icon:hover {
923
+ opacity: 1;
924
+ transform: scale(1.2);
925
+ text-shadow: 0 0 5px rgba(0,0,0,0.6);
926
+ }
927
+
928
+ .table-activities .activities-sort-icon {
929
+ color: #ffffff !important;
930
+ text-shadow: 0 0 3px rgba(0,0,0,0.4);
931
+ }
932
+
933
+ .table-activities .activities-sort-icon:hover {
934
+ opacity: 1;
935
+ transform: scale(1.2);
936
+ text-shadow: 0 0 5px rgba(0,0,0,0.6);
937
+ }
938
+
939
+ /* Column widths for activities table */
940
+ .table-activities th:nth-child(1), .table-activities td:nth-child(1) { /* Activity Name */
941
+ width: 70%;
942
+ min-width: 300px;
943
+ text-align: left;
944
+ padding-left: 180px;
945
+ }
946
+
947
+ .table-activities th:nth-child(2), .table-activities td:nth-child(2) { /* Visit Count */
948
+ width: 30%;
949
+ min-width: 150px;
950
+ text-align: center;
951
+ }
952
+
823
953
  /* Modern Activity Item Styling */
824
954
  .activity-item {
825
955
  background: #ffffff;
@@ -1109,254 +1239,97 @@
1109
1239
  </div>
1110
1240
  </div>
1111
1241
 
1112
- <!-- Tested Activities List -->
1242
+ <!-- Activities Coverage -->
1113
1243
  <div class="section-block">
1114
1244
  <h2 class="section-title">Activities Coverage</h2>
1115
-
1116
- <div class="card">
1117
- <div class="card-header bg-primary text-white">
1118
- <div class="d-flex justify-content-between align-items-center">
1119
- <span><i class="bi bi-app"></i> Activities Coverage Overview</span>
1120
- <span class="badge bg-light text-dark" style="font-size: 1.1em; font-weight: 600;">Coverage: {{ coverage_percent }}%</span>
1245
+
1246
+ <!-- Search Controls for Activities -->
1247
+ <div class="mb-4">
1248
+ <div class="d-flex align-items-center">
1249
+ <div style="width: 33%;">
1250
+ <div class="property-search-container">
1251
+ <input type="text" class="form-control property-search-input property-stats-search-simple"
1252
+ id="activities-search"
1253
+ placeholder="Search activities by name..."
1254
+ data-target="activities-container"
1255
+ data-item-class="activity-row"
1256
+ data-pagination="activities-pagination"
1257
+ data-page-size="activities-page-size">
1258
+ <button class="property-search-icon-btn" type="button" id="activities-search-btn">
1259
+ <i class="bi bi-search"></i>
1260
+ </button>
1261
+ </div>
1121
1262
  </div>
1122
- </div>
1123
- <div class="card-body">
1124
- <div class="alert alert-info mb-3" style="border-left: 4px solid #17a2b8; background-color: #f8f9fa;">
1125
- <small class="text-muted">
1126
- <i class="bi bi-info-circle me-1"></i>
1127
- <strong>Visit Count Explanation:</strong>
1128
- The number after the <i class="bi bi-eye"></i> icon indicates how many times each Activity was visited during testing.
1129
- </small>
1263
+ <div class="ms-3">
1264
+ <small class="text-muted search-results-count" id="activities-search-results"></small>
1130
1265
  </div>
1131
-
1132
- <!-- Navigation Tabs -->
1133
- <ul class="nav nav-tabs mb-3" id="activitiesTabs" role="tablist">
1134
- <li class="nav-item" role="presentation">
1135
- <button class="nav-link active" id="tested-tab" data-bs-toggle="tab"
1136
- data-bs-target="#tested-activities" type="button" role="tab"
1137
- aria-controls="tested-activities" aria-selected="true">
1138
- <i class="bi bi-check-circle"></i> Tested Activities ({{ tested_activities|length }})
1139
- </button>
1140
- </li>
1141
- <li class="nav-item" role="presentation">
1142
- <button class="nav-link" id="all-tab" data-bs-toggle="tab"
1143
- data-bs-target="#all-activities" type="button" role="tab"
1144
- aria-controls="all-activities" aria-selected="false">
1145
- <i class="bi bi-app"></i> All Activities ({{ total_activities|length }})
1146
- </button>
1147
- </li>
1148
- </ul>
1149
-
1150
- <!-- Tab Content -->
1151
- <div class="tab-content" id="activitiesTabContent">
1152
- <!-- Tested Activities Tab -->
1153
- <div class="tab-pane fade show active" id="tested-activities" role="tabpanel"
1154
- aria-labelledby="tested-tab">
1155
- <div class="d-flex justify-content-between align-items-center mb-3">
1156
- <h5 class="mb-0 text-success">
1157
- <i class="bi bi-check-circle-fill"></i> Tested Activities
1158
- </h5>
1159
- <span class="badge bg-success" style="font-size: 1.0em; font-weight: 500;">{{ tested_activities|length }} / {{ total_activities_count }}</span>
1160
- </div>
1161
-
1162
- <!-- Combined Search and Sort Controls for Tested Activities -->
1163
- <div class="search-sort-controls-modern mb-4">
1164
- <div class="d-flex align-items-center gap-4">
1165
- <!-- Search Section -->
1166
- <div class="search-section d-flex align-items-center" style="width: 600px; flex-shrink: 0;">
1167
- <div class="search-icon-wrapper me-3">
1168
- <i class="bi bi-search"></i>
1169
- </div>
1170
- <div class="flex-grow-1">
1171
- <div class="input-group">
1172
- <input type="text" class="form-control activity-search-input"
1173
- id="tested-activity-search"
1174
- placeholder="Search activities..."
1175
- data-target="tested-activities-container"
1176
- data-item-class="tested-activity"
1177
- data-pagination="tested-pagination"
1178
- data-page-size="tested-page-size">
1179
- <button class="btn search-btn" type="button"
1180
- data-target="tested-activity-search">
1181
- <i class="bi bi-search"></i>
1182
- </button>
1183
- <button class="btn btn-outline-secondary search-clear-btn" type="button"
1184
- data-target="tested-activity-search">
1185
- <i class="bi bi-x-lg"></i>
1186
- </button>
1187
- </div>
1188
- <small class="text-muted search-results-count" id="tested-search-results"></small>
1189
- </div>
1190
- </div>
1266
+ </div>
1267
+ </div>
1191
1268
 
1192
- <!-- Sort Section -->
1193
- <div class="sort-section d-flex align-items-center gap-3" style="margin-left: auto;">
1194
- <div class="sort-label d-flex align-items-center gap-2">
1195
- <i class="bi bi-funnel-fill text-muted"></i>
1196
- <span class="text-muted fw-medium">Sort:</span>
1197
- </div>
1198
- <button type="button" class="btn-sort-modern activity-sort-btn" data-sort="traversal" data-order="desc">
1199
- <div class="btn-content">
1200
- <i class="bi bi-eye btn-icon"></i>
1201
- <span class="btn-text">Visit Count</span>
1202
- <i class="bi bi-arrow-down sort-icon btn-arrow"></i>
1203
- </div>
1204
- </button>
1205
- </div>
1206
- </div>
1207
- </div>
1208
-
1209
- <div class="activities-container">
1210
- <div class="activity-list">
1211
- {% if tested_activities|length > 0 %}
1212
- <div id="tested-activities-container">
1213
- {% for activity in tested_activities %}
1214
- <div class="activity-item tested-activity" data-page="1">
1215
- <div class="activity-content">
1216
- <i class="bi bi-check-circle-fill text-success me-2"></i>
1217
- <span class="activity-name">{{ activity }}</span>
1218
- </div>
1219
- {% if activity in activity_count_history %}
1220
- <span class="badge bg-info text-white traversal-badge">
1221
- <i class="bi bi-eye"></i> {{ activity_count_history[activity] }} times
1222
- </span>
1223
- {% endif %}
1224
- </div>
1225
- {% endfor %}
1226
- </div>
1269
+ <div class="table-responsive">
1270
+ <table class="table table-custom table-activities">
1271
+ <thead>
1272
+ <tr>
1273
+ <th>Activity Name</th>
1274
+ <th>Visit Count <i class="bi bi-arrow-down-up text-muted sort-icon activities-sort-icon" id="visit-count-sort" data-column="visit-count" data-order="none" style="cursor: pointer;"></i></th>
1275
+ </tr>
1276
+ </thead>
1277
+ <tbody id="activities-container">
1278
+ {% if total_activities|length > 0 %}
1279
+ {% for activity in total_activities %}
1280
+ <tr class="activity-row" data-page="1"
1281
+ data-activity-name="{{ activity }}"
1282
+ data-visit-count="{{ activity_count_history[activity] if activity in activity_count_history else 0 }}">
1283
+ <td>
1284
+ {% if activity in tested_activities %}
1285
+ <i class="bi bi-check-circle-fill text-success me-2"></i>
1227
1286
  {% else %}
1228
- <div class="alert alert-warning">
1229
- No tested activities detected
1230
- </div>
1287
+ <i class="bi bi-dash-circle text-secondary me-2"></i>
1231
1288
  {% endif %}
1232
- </div>
1233
- <!-- Pagination for Tested Activities -->
1234
- <div class="pagination-container d-flex justify-content-between align-items-center">
1235
- <div class="d-flex align-items-center">
1236
- <label for="tested-page-size" class="form-label me-2 mb-0">Show:</label>
1237
- <select class="form-select form-select-sm" id="tested-page-size" style="width: auto;">
1238
- <option value="5">5</option>
1239
- <option value="10" selected>10</option>
1240
- <option value="20">20</option>
1241
- <option value="50">50</option>
1242
- <option value="100">100</option>
1243
- </select>
1244
- </div>
1245
- <nav aria-label="Tested Activities Pagination">
1246
- <ul class="pagination pagination-sm mb-0" id="tested-pagination">
1247
- <!-- Pagination will be generated by JavaScript -->
1248
- </ul>
1249
- </nav>
1250
- </div>
1251
- </div>
1252
- </div>
1253
-
1254
- <!-- All Activities Tab -->
1255
- <div class="tab-pane fade" id="all-activities" role="tabpanel"
1256
- aria-labelledby="all-tab">
1257
- <div class="d-flex justify-content-between align-items-center mb-3">
1258
- <h5 class="mb-0 text-primary">
1259
- <i class="bi bi-app"></i> All Activities Overview
1260
- </h5>
1261
- <span class="badge bg-primary" style="font-size: 1.0em; font-weight: 500;">Total: {{ total_activities|length }}</span>
1262
- </div>
1263
-
1264
- <!-- Combined Search and Sort Controls for All Activities -->
1265
- <div class="search-sort-controls-modern mb-4">
1266
- <div class="d-flex align-items-center gap-4">
1267
- <!-- Search Section -->
1268
- <div class="search-section d-flex align-items-center" style="width: 600px; flex-shrink: 0;">
1269
- <div class="search-icon-wrapper me-3">
1270
- <i class="bi bi-search"></i>
1271
- </div>
1272
- <div class="flex-grow-1">
1273
- <div class="input-group">
1274
- <input type="text" class="form-control activity-search-input"
1275
- id="all-activity-search"
1276
- placeholder="Search activities..."
1277
- data-target="all-activities-container"
1278
- data-item-class="all-activity"
1279
- data-pagination="all-pagination"
1280
- data-page-size="all-page-size">
1281
- <button class="btn search-btn" type="button"
1282
- data-target="all-activity-search">
1283
- <i class="bi bi-search"></i>
1284
- </button>
1285
- <button class="btn btn-outline-secondary search-clear-btn" type="button"
1286
- data-target="all-activity-search">
1287
- <i class="bi bi-x-lg"></i>
1288
- </button>
1289
- </div>
1290
- <small class="text-muted search-results-count" id="all-search-results"></small>
1291
- </div>
1292
- </div>
1293
-
1294
- <!-- Sort Section -->
1295
- <div class="sort-section d-flex align-items-center gap-3" style="margin-left: auto;">
1296
- <div class="sort-label d-flex align-items-center gap-2">
1297
- <i class="bi bi-funnel-fill text-muted"></i>
1298
- <span class="text-muted fw-medium">Sort:</span>
1299
- </div>
1300
- <button type="button" class="btn-sort-modern activity-sort-btn" data-sort="traversal" data-order="desc">
1301
- <div class="btn-content">
1302
- <i class="bi bi-eye btn-icon"></i>
1303
- <span class="btn-text">Visit Count</span>
1304
- <i class="bi bi-arrow-down sort-icon btn-arrow"></i>
1305
- </div>
1306
- </button>
1307
- </div>
1308
- </div>
1309
- </div>
1310
-
1311
- <div class="activities-container">
1312
- <div class="activity-list">
1313
- {% if total_activities|length > 0 %}
1314
- <div id="all-activities-container">
1315
- {% for activity in total_activities %}
1316
- <div class="activity-item all-activity" data-page="1">
1317
- <div class="activity-content">
1318
- {% if activity in tested_activities %}
1319
- <i class="bi bi-check-circle-fill text-success me-2"></i>
1320
- {% else %}
1321
- <i class="bi bi-dash-circle text-secondary me-2"></i>
1322
- {% endif %}
1323
- <span class="activity-name">{{ activity }}</span>
1324
- </div>
1325
- {% if activity in activity_count_history %}
1326
- <span class="badge bg-info text-white traversal-badge">
1327
- <i class="bi bi-eye"></i> {{ activity_count_history[activity] }} times
1328
- </span>
1329
- {% endif %}
1330
- </div>
1331
- {% endfor %}
1332
- </div>
1289
+ <span class="activity-name">{{ activity }}</span>
1290
+ </td>
1291
+ <td>
1292
+ {% if activity in activity_count_history %}
1293
+ <span class="badge bg-info text-white">
1294
+ <i class="bi bi-eye"></i> {{ activity_count_history[activity] }} times
1295
+ </span>
1333
1296
  {% else %}
1334
- <div class="alert alert-warning">
1335
- No activities information available
1336
- </div>
1297
+ <span class="badge bg-secondary text-white">
1298
+ <i class="bi bi-dash"></i> 0 times
1299
+ </span>
1337
1300
  {% endif %}
1338
- </div>
1339
- <!-- Pagination for All Activities -->
1340
- <div class="pagination-container d-flex justify-content-between align-items-center">
1341
- <div class="d-flex align-items-center">
1342
- <label for="all-page-size" class="form-label me-2 mb-0">Show:</label>
1343
- <select class="form-select form-select-sm" id="all-page-size" style="width: auto;">
1344
- <option value="5">5</option>
1345
- <option value="10" selected>10</option>
1346
- <option value="20">20</option>
1347
- <option value="50">50</option>
1348
- <option value="100">100</option>
1349
- </select>
1301
+ </td>
1302
+ </tr>
1303
+ {% endfor %}
1304
+ {% else %}
1305
+ <tr>
1306
+ <td colspan="2" class="text-center">
1307
+ <div class="alert alert-warning mb-0">
1308
+ No activities information available
1350
1309
  </div>
1351
- <nav aria-label="All Activities Pagination">
1352
- <ul class="pagination pagination-sm mb-0" id="all-pagination">
1353
- <!-- Pagination will be generated by JavaScript -->
1354
- </ul>
1355
- </nav>
1356
- </div>
1357
- </div>
1358
- </div>
1310
+ </td>
1311
+ </tr>
1312
+ {% endif %}
1313
+ </tbody>
1314
+ </table>
1315
+
1316
+ <!-- Pagination for Activities -->
1317
+ <div class="d-flex justify-content-between align-items-center mt-3">
1318
+ <div class="d-flex align-items-center">
1319
+ <label for="activities-page-size" class="form-label me-2 mb-0">Show:</label>
1320
+ <select class="form-select form-select-sm" id="activities-page-size" style="width: auto;">
1321
+ <option value="5">5</option>
1322
+ <option value="10" selected>10</option>
1323
+ <option value="20">20</option>
1324
+ <option value="50">50</option>
1325
+ <option value="100">100</option>
1326
+ </select>
1359
1327
  </div>
1328
+ <nav aria-label="Activities Pagination">
1329
+ <ul class="pagination pagination-sm mb-0" id="activities-pagination">
1330
+ <!-- Pagination will be generated by JavaScript -->
1331
+ </ul>
1332
+ </nav>
1360
1333
  </div>
1361
1334
  </div>
1362
1335
  </div>
@@ -1518,6 +1491,7 @@
1518
1491
 
1519
1492
  <!-- Property Violations List -->
1520
1493
  {% if take_screenshots %}
1494
+ {% if property_violations %}
1521
1495
  <div class="section-block">
1522
1496
  <h2 class="section-title">Property Violations</h2>
1523
1497
  <div class="table-responsive">
@@ -1526,9 +1500,7 @@
1526
1500
  <tr>
1527
1501
  <th>Index</th>
1528
1502
  <th>Property Name</th>
1529
- <th>Precondition Page</th>
1530
1503
  <th>Interaction Scenario Pages</th>
1531
- <th>Postcondition Page</th>
1532
1504
  </tr>
1533
1505
  </thead>
1534
1506
  <tbody id="property-violations-container">
@@ -1536,14 +1508,12 @@
1536
1508
  <tr class="property-violation-row" data-page="1">
1537
1509
  <td>{{ violation.index }}</td>
1538
1510
  <td><span class="badge bg-light text-dark badge-custom">{{ violation.property_name }}</span></td>
1539
- <td><a href="#{{ violation.precondition_page }}" class="link-button">{{ violation.precondition_page }}</a></td>
1540
1511
  <td><a href="#{{ violation.interaction_pages[0] }}" class="link-button">{{ violation.interaction_pages[0] }} ~ {{ violation.interaction_pages[1] }}</a></td>
1541
- <td><a href="#{{ violation.postcondition_page }}" class="link-button">{{ violation.postcondition_page }}</a></td>
1542
1512
  </tr>
1543
1513
  {% endfor %}
1544
1514
  </tbody>
1545
1515
  </table>
1546
-
1516
+
1547
1517
  <!-- Pagination for Property Violations -->
1548
1518
  <div class="d-flex justify-content-between align-items-center mt-3">
1549
1519
  <div class="d-flex align-items-center">
@@ -1564,6 +1534,14 @@
1564
1534
  </div>
1565
1535
  </div>
1566
1536
  </div>
1537
+ {% else %}
1538
+ <div class="section-block">
1539
+ <h2 class="section-title">Property Violations</h2>
1540
+ <div class="alert alert-info text-center">
1541
+ <i class="bi bi-info-circle"></i> No property violations detected in this test session.
1542
+ </div>
1543
+ </div>
1544
+ {% endif %}
1567
1545
  {% endif %}
1568
1546
 
1569
1547
  <!-- Property Checking Statistics -->
@@ -1571,29 +1549,23 @@
1571
1549
  <h2 class="section-title">Property Checking Statistics</h2>
1572
1550
 
1573
1551
  <!-- Search Controls for Property Statistics -->
1574
- <div class="search-controls-modern mb-4">
1552
+ <div class="mb-4">
1575
1553
  <div class="d-flex align-items-center">
1576
- <div class="search-icon-wrapper me-3">
1577
- <i class="bi bi-search"></i>
1578
- </div>
1579
- <div class="flex-grow-1">
1580
- <div class="input-group">
1581
- <input type="text" class="form-control property-search-input"
1582
- id="property-stats-search"
1583
- placeholder="Search properties by name..."
1554
+ <div style="width: 33%;">
1555
+ <div class="property-search-container">
1556
+ <input type="text" class="form-control property-search-input property-stats-search-simple"
1557
+ id="property-stats-search"
1558
+ placeholder="Search properties by name..."
1584
1559
  data-target="property-stats-container"
1585
1560
  data-item-class="property-stat-row"
1586
1561
  data-pagination="stats-pagination"
1587
1562
  data-page-size="stats-page-size">
1588
- <button class="btn btn-primary search-btn" type="button"
1589
- data-target="property-stats-search">
1563
+ <button class="property-search-icon-btn" type="button" id="property-search-btn">
1590
1564
  <i class="bi bi-search"></i>
1591
1565
  </button>
1592
- <button class="btn btn-outline-secondary search-clear-btn" type="button"
1593
- data-target="property-stats-search">
1594
- <i class="bi bi-x-lg"></i>
1595
- </button>
1596
1566
  </div>
1567
+ </div>
1568
+ <div class="ms-3">
1597
1569
  <small class="text-muted search-results-count" id="property-search-results"></small>
1598
1570
  </div>
1599
1571
  </div>
@@ -2097,16 +2069,18 @@
2097
2069
  // Initialize crash events functionality
2098
2070
  initCrashAnalysis();
2099
2071
 
2100
- // Initialize pagination for Activities lists
2101
- initPagination('tested-activities-container', 'tested-activity', 'tested-pagination', 'tested-page-size');
2102
- initPagination('all-activities-container', 'all-activity', 'all-pagination', 'all-page-size');
2103
-
2072
+ // Initialize pagination for Activities table
2073
+ initPagination('activities-container', 'activity-row', 'activities-pagination', 'activities-page-size');
2074
+
2104
2075
  // Initialize activity sorting
2105
- initActivitySorting();
2106
-
2076
+ initActivitiesSorting();
2077
+
2107
2078
  // Initialize activity searching
2108
- initActivitySearching();
2109
-
2079
+ initActivitiesSearching();
2080
+
2081
+ // Initialize activities page size selector
2082
+ initActivitiesPageSize();
2083
+
2110
2084
  // Initialize property statistics searching
2111
2085
  initPropertySearching();
2112
2086
 
@@ -2188,16 +2162,17 @@
2188
2162
  }
2189
2163
  }
2190
2164
 
2191
- // Simplified sorting function for Fails and Errors columns
2165
+ // Simplified sorting function for Fails and Errors columns (Property Checking Statistics only)
2192
2166
  function initSorting() {
2193
- const sortIcons = document.querySelectorAll('.sort-icon');
2194
-
2167
+ // Only select sort icons that are NOT activities sort icons
2168
+ const sortIcons = document.querySelectorAll('.sort-icon:not(.activities-sort-icon)');
2169
+
2195
2170
  sortIcons.forEach(function(icon) {
2196
2171
  icon.addEventListener('click', function() {
2197
2172
  const column = this.dataset.column;
2198
2173
  const currentOrder = this.dataset.order;
2199
-
2200
- // Reset all other sort icons
2174
+
2175
+ // Reset all other property sort icons (not activities)
2201
2176
  sortIcons.forEach(function(otherIcon) {
2202
2177
  if (otherIcon !== icon) {
2203
2178
  otherIcon.dataset.order = 'none';
@@ -2205,7 +2180,7 @@
2205
2180
  otherIcon.style.color = '#6c757d';
2206
2181
  }
2207
2182
  });
2208
-
2183
+
2209
2184
  // Toggle current sort order
2210
2185
  let newOrder;
2211
2186
  if (currentOrder === 'none' || currentOrder === 'desc') {
@@ -2217,7 +2192,7 @@
2217
2192
  this.className = 'bi bi-arrow-down sort-icon active desc';
2218
2193
  this.style.color = '#dc3545';
2219
2194
  }
2220
-
2195
+
2221
2196
  this.dataset.order = newOrder;
2222
2197
  sortTable(column, newOrder);
2223
2198
  });
@@ -2922,12 +2897,11 @@
2922
2897
  // Property statistics searching function
2923
2898
  function initPropertySearching() {
2924
2899
  const searchInput = document.getElementById('property-stats-search');
2925
- const searchButton = document.querySelector('.search-btn[data-target="property-stats-search"]');
2926
- const clearButton = document.querySelector('[data-target="property-stats-search"].search-clear-btn');
2927
-
2900
+ const searchButton = document.getElementById('property-search-btn');
2901
+
2928
2902
  if (!searchInput) return;
2929
-
2930
- // Search on Enter key
2903
+
2904
+ // Search on Enter key and clear on Escape
2931
2905
  searchInput.addEventListener('keydown', function(e) {
2932
2906
  if (e.key === 'Enter') {
2933
2907
  e.preventDefault();
@@ -2936,7 +2910,7 @@
2936
2910
  clearPropertySearch(this);
2937
2911
  }
2938
2912
  });
2939
-
2913
+
2940
2914
  // Search button functionality
2941
2915
  if (searchButton) {
2942
2916
  searchButton.addEventListener('click', function() {
@@ -2944,13 +2918,6 @@
2944
2918
  });
2945
2919
  }
2946
2920
 
2947
- // Clear button functionality
2948
- if (clearButton) {
2949
- clearButton.addEventListener('click', function() {
2950
- clearPropertySearch(searchInput);
2951
- });
2952
- }
2953
-
2954
2921
  function performPropertySearch(searchInput) {
2955
2922
  const searchTerm = searchInput.value.toLowerCase().trim();
2956
2923
  const container = document.getElementById('property-stats-container');
@@ -3164,6 +3131,360 @@
3164
3131
  const currentItemsPerPage = pageSizeSelect ? parseInt(pageSizeSelect.value) : 10;
3165
3132
  goToPage(1, containerId, itemClass, currentItemsPerPage, paginationId);
3166
3133
  }
3134
+
3135
+ // Activities table searching function
3136
+ function initActivitiesSearching() {
3137
+ const searchInput = document.getElementById('activities-search');
3138
+ const searchButton = document.getElementById('activities-search-btn');
3139
+
3140
+ if (!searchInput) return;
3141
+
3142
+ // Search on Enter key and clear on Escape
3143
+ searchInput.addEventListener('keydown', function(e) {
3144
+ if (e.key === 'Enter') {
3145
+ e.preventDefault();
3146
+ performActivitiesSearch(this);
3147
+ } else if (e.key === 'Escape') {
3148
+ clearActivitiesSearch(this);
3149
+ }
3150
+ });
3151
+
3152
+ // Search button functionality
3153
+ if (searchButton) {
3154
+ searchButton.addEventListener('click', function() {
3155
+ performActivitiesSearch(searchInput);
3156
+ });
3157
+ }
3158
+
3159
+ function performActivitiesSearch(searchInput) {
3160
+ const searchTerm = searchInput.value.toLowerCase().trim();
3161
+ const container = document.getElementById('activities-container');
3162
+ const rows = container.querySelectorAll('.activity-row');
3163
+ const resultsCount = document.getElementById('activities-search-results');
3164
+
3165
+ let visibleCount = 0;
3166
+
3167
+ rows.forEach(function(row) {
3168
+ const activityName = row.querySelector('.activity-name').textContent.toLowerCase();
3169
+
3170
+ // If no search term, show all rows
3171
+ if (!searchTerm) {
3172
+ row.removeAttribute('data-search-visible');
3173
+ visibleCount++;
3174
+ } else {
3175
+ const matches = activityName.includes(searchTerm);
3176
+ if (matches) {
3177
+ row.setAttribute('data-search-visible', 'true');
3178
+ visibleCount++;
3179
+ } else {
3180
+ row.setAttribute('data-search-visible', 'false');
3181
+ }
3182
+ }
3183
+ });
3184
+
3185
+ console.log('Search performed:', {searchTerm, visibleCount, totalRows: rows.length});
3186
+
3187
+ // Update results count
3188
+ if (resultsCount) {
3189
+ if (searchTerm) {
3190
+ resultsCount.textContent = `Found ${visibleCount} of ${rows.length} activities`;
3191
+ } else {
3192
+ resultsCount.textContent = '';
3193
+ }
3194
+ }
3195
+
3196
+ // Immediately show/hide rows based on search before pagination update
3197
+ rows.forEach(function(row) {
3198
+ const searchVisible = row.getAttribute('data-search-visible');
3199
+ if (searchVisible === null || searchVisible === 'true') {
3200
+ row.style.display = '';
3201
+ } else {
3202
+ row.style.display = 'none';
3203
+ }
3204
+ });
3205
+
3206
+ console.log('Rows visibility updated, calling pagination update...');
3207
+
3208
+ // Update pagination after search
3209
+ updateActivitiesPagination();
3210
+ }
3211
+
3212
+ function clearActivitiesSearch(searchInput) {
3213
+ searchInput.value = '';
3214
+ performActivitiesSearch(searchInput);
3215
+ searchInput.focus();
3216
+ }
3217
+ }
3218
+
3219
+ // Initialize Activities page size selector
3220
+ function initActivitiesPageSize() {
3221
+ const pageSizeSelect = document.getElementById('activities-page-size');
3222
+
3223
+ if (!pageSizeSelect) return;
3224
+
3225
+ // Remove existing event listener to prevent duplicate bindings
3226
+ if (!pageSizeSelect.hasAttribute('data-activities-listener-bound')) {
3227
+ pageSizeSelect.addEventListener('change', function() {
3228
+ console.log('Activities page size changed to:', this.value);
3229
+ updateActivitiesPagination();
3230
+ });
3231
+ // Mark as having listener bound
3232
+ pageSizeSelect.setAttribute('data-activities-listener-bound', 'true');
3233
+ }
3234
+ }
3235
+
3236
+ // Activities table sorting function
3237
+ function initActivitiesSorting() {
3238
+ const sortIcon = document.getElementById('visit-count-sort');
3239
+
3240
+ if (!sortIcon) return;
3241
+
3242
+ sortIcon.addEventListener('click', function(e) {
3243
+ e.preventDefault();
3244
+ e.stopPropagation();
3245
+
3246
+ console.log('Sort icon clicked, current order:', this.dataset.order);
3247
+
3248
+ const currentOrder = this.dataset.order || 'none';
3249
+ const container = document.getElementById('activities-container');
3250
+ const rows = Array.from(container.querySelectorAll('.activity-row'));
3251
+
3252
+ console.log('Found rows:', rows.length);
3253
+
3254
+ // Reset only activities sort icons (not property stats sort icons)
3255
+ document.querySelectorAll('.activities-sort-icon').forEach(icon => {
3256
+ if (icon !== this) {
3257
+ icon.className = 'bi bi-arrow-down-up text-muted sort-icon activities-sort-icon';
3258
+ icon.dataset.order = 'none';
3259
+ }
3260
+ });
3261
+
3262
+ let newOrder;
3263
+ if (currentOrder === 'none' || currentOrder === 'desc') {
3264
+ newOrder = 'asc';
3265
+ this.className = 'bi bi-arrow-up text-primary sort-icon activities-sort-icon';
3266
+ } else {
3267
+ newOrder = 'desc';
3268
+ this.className = 'bi bi-arrow-down text-primary sort-icon activities-sort-icon';
3269
+ }
3270
+
3271
+ this.dataset.order = newOrder;
3272
+ console.log('New order set to:', newOrder);
3273
+
3274
+ // Sort rows
3275
+ rows.sort((a, b) => {
3276
+ const aCount = parseInt(a.dataset.visitCount) || 0;
3277
+ const bCount = parseInt(b.dataset.visitCount) || 0;
3278
+
3279
+ if (newOrder === 'asc') {
3280
+ return aCount - bCount;
3281
+ } else {
3282
+ return bCount - aCount;
3283
+ }
3284
+ });
3285
+
3286
+ // Clear container and re-append sorted rows
3287
+ container.innerHTML = '';
3288
+ rows.forEach(row => container.appendChild(row));
3289
+
3290
+ console.log('Sorting completed');
3291
+
3292
+ // Properly update pagination after sorting
3293
+ updateActivitiesPagination();
3294
+ });
3295
+ }
3296
+
3297
+ // Function to update Activities pagination after sorting
3298
+ function updateActivitiesPagination() {
3299
+ const container = document.getElementById('activities-container');
3300
+ const pageSizeSelect = document.getElementById('activities-page-size');
3301
+ const paginationElement = document.getElementById('activities-pagination');
3302
+
3303
+ if (!container || !paginationElement) return;
3304
+
3305
+ const allRows = Array.from(container.querySelectorAll('.activity-row'));
3306
+ const itemsPerPage = pageSizeSelect ? parseInt(pageSizeSelect.value) : 10;
3307
+
3308
+ // Filter visible rows (considering search)
3309
+ const visibleRows = allRows.filter(row => {
3310
+ const searchVisible = row.getAttribute('data-search-visible');
3311
+ return searchVisible === null || searchVisible === 'true';
3312
+ });
3313
+
3314
+ const totalItems = visibleRows.length;
3315
+ const totalPages = Math.max(1, Math.ceil(totalItems / itemsPerPage));
3316
+
3317
+ console.log('Updating pagination:', {totalItems, itemsPerPage, totalPages});
3318
+
3319
+ // Clear pagination
3320
+ paginationElement.innerHTML = '';
3321
+
3322
+ // Find pagination container
3323
+ const paginationContainer = paginationElement.closest('.d-flex');
3324
+
3325
+ // Don't show pagination if there's only one page or no items
3326
+ if (totalPages <= 1) {
3327
+ if (paginationContainer) {
3328
+ paginationContainer.style.display = 'none';
3329
+ }
3330
+ // Show visible rows and hide invisible rows
3331
+ allRows.forEach(row => {
3332
+ const searchVisible = row.getAttribute('data-search-visible');
3333
+ if (searchVisible === null || searchVisible === 'true') {
3334
+ row.style.display = '';
3335
+ } else {
3336
+ row.style.display = 'none';
3337
+ }
3338
+ });
3339
+ return;
3340
+ }
3341
+
3342
+ // Show the pagination container when needed
3343
+ if (paginationContainer) {
3344
+ paginationContainer.style.display = '';
3345
+ }
3346
+
3347
+ // Create Previous button
3348
+ const prevLi = document.createElement('li');
3349
+ prevLi.className = 'page-item';
3350
+ prevLi.id = 'activities-prev-page';
3351
+
3352
+ const prevA = document.createElement('a');
3353
+ prevA.className = 'page-link';
3354
+ prevA.href = '#';
3355
+ prevA.innerHTML = '&laquo;';
3356
+ prevA.addEventListener('click', function(e) {
3357
+ e.preventDefault();
3358
+ const currentPage = getCurrentActivitiesPage();
3359
+ if (currentPage > 1) {
3360
+ goToActivitiesPage(currentPage - 1, totalPages, itemsPerPage);
3361
+ }
3362
+ });
3363
+
3364
+ prevLi.appendChild(prevA);
3365
+ paginationElement.appendChild(prevLi);
3366
+
3367
+ // Create page number buttons
3368
+ for (let i = 1; i <= totalPages; i++) {
3369
+ const li = document.createElement('li');
3370
+ li.className = `page-item ${i === 1 ? 'active' : ''}`;
3371
+ li.setAttribute('data-page', i);
3372
+
3373
+ const a = document.createElement('a');
3374
+ a.className = 'page-link';
3375
+ a.href = '#';
3376
+ a.textContent = i;
3377
+ a.addEventListener('click', function(e) {
3378
+ e.preventDefault();
3379
+ goToActivitiesPage(i, totalPages, itemsPerPage);
3380
+ });
3381
+
3382
+ li.appendChild(a);
3383
+ paginationElement.appendChild(li);
3384
+ }
3385
+
3386
+ // Create Next button
3387
+ const nextLi = document.createElement('li');
3388
+ nextLi.className = 'page-item';
3389
+ nextLi.id = 'activities-next-page';
3390
+
3391
+ const nextA = document.createElement('a');
3392
+ nextA.className = 'page-link';
3393
+ nextA.href = '#';
3394
+ nextA.innerHTML = '&raquo;';
3395
+ nextA.addEventListener('click', function(e) {
3396
+ e.preventDefault();
3397
+ const currentPage = getCurrentActivitiesPage();
3398
+ if (currentPage < totalPages) {
3399
+ goToActivitiesPage(currentPage + 1, totalPages, itemsPerPage);
3400
+ }
3401
+ });
3402
+
3403
+ nextLi.appendChild(nextA);
3404
+ paginationElement.appendChild(nextLi);
3405
+
3406
+ // Show first page and update navigation buttons
3407
+ goToActivitiesPage(1, totalPages, itemsPerPage);
3408
+ }
3409
+
3410
+ // Function to navigate to specific page in Activities table
3411
+ function goToActivitiesPage(pageNumber, totalPages, itemsPerPage) {
3412
+ const container = document.getElementById('activities-container');
3413
+ const paginationElement = document.getElementById('activities-pagination');
3414
+
3415
+ if (!container) return;
3416
+
3417
+ const allRows = Array.from(container.querySelectorAll('.activity-row'));
3418
+
3419
+ // Filter visible rows (considering search)
3420
+ const visibleRows = allRows.filter(row => {
3421
+ const searchVisible = row.getAttribute('data-search-visible');
3422
+ return searchVisible === null || searchVisible === 'true';
3423
+ });
3424
+
3425
+ const startIndex = (pageNumber - 1) * itemsPerPage;
3426
+ const endIndex = startIndex + itemsPerPage;
3427
+
3428
+ console.log('Going to page:', {pageNumber, startIndex, endIndex, totalVisible: visibleRows.length});
3429
+
3430
+ // Hide all rows first
3431
+ allRows.forEach(row => {
3432
+ row.style.display = 'none';
3433
+ });
3434
+
3435
+ // Show rows for current page
3436
+ visibleRows.forEach((row, index) => {
3437
+ if (index >= startIndex && index < endIndex) {
3438
+ row.style.display = '';
3439
+ }
3440
+ });
3441
+
3442
+ // Update pagination active state
3443
+ if (paginationElement) {
3444
+ // Update page number buttons
3445
+ const pageItems = paginationElement.querySelectorAll('.page-item[data-page]');
3446
+ pageItems.forEach((item) => {
3447
+ const page = parseInt(item.getAttribute('data-page'));
3448
+ if (page === pageNumber) {
3449
+ item.classList.add('active');
3450
+ } else {
3451
+ item.classList.remove('active');
3452
+ }
3453
+ });
3454
+
3455
+ // Update Previous button state
3456
+ const prevButton = paginationElement.querySelector('#activities-prev-page');
3457
+ if (prevButton) {
3458
+ if (pageNumber <= 1) {
3459
+ prevButton.classList.add('disabled');
3460
+ } else {
3461
+ prevButton.classList.remove('disabled');
3462
+ }
3463
+ }
3464
+
3465
+ // Update Next button state
3466
+ const nextButton = paginationElement.querySelector('#activities-next-page');
3467
+ if (nextButton) {
3468
+ if (pageNumber >= totalPages) {
3469
+ nextButton.classList.add('disabled');
3470
+ } else {
3471
+ nextButton.classList.remove('disabled');
3472
+ }
3473
+ }
3474
+ }
3475
+ }
3476
+
3477
+ // Function to get current active page in Activities pagination
3478
+ function getCurrentActivitiesPage() {
3479
+ const paginationElement = document.getElementById('activities-pagination');
3480
+ if (!paginationElement) return 1;
3481
+
3482
+ const activeItem = paginationElement.querySelector('.page-item.active[data-page]');
3483
+ if (activeItem) {
3484
+ return parseInt(activeItem.getAttribute('data-page'));
3485
+ }
3486
+ return 1;
3487
+ }
3167
3488
  </script>
3168
3489
  </body>
3169
3490
  </html>