GameSentenceMiner 2.17.1__py3-none-any.whl → 2.17.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 GameSentenceMiner might be problematic. Click here for more details.
- GameSentenceMiner/anki.py +25 -1
- GameSentenceMiner/config_gui.py +19 -1
- GameSentenceMiner/gsm.py +13 -18
- GameSentenceMiner/obs.py +4 -2
- GameSentenceMiner/ocr/owocr_helper.py +1 -1
- GameSentenceMiner/owocr/owocr/run.py +2 -2
- GameSentenceMiner/util/configuration.py +7 -5
- GameSentenceMiner/util/db.py +176 -8
- GameSentenceMiner/util/downloader/download_tools.py +57 -24
- GameSentenceMiner/util/get_overlay_coords.py +3 -0
- GameSentenceMiner/util/gsm_utils.py +0 -54
- GameSentenceMiner/web/database_api.py +12 -1
- GameSentenceMiner/web/gsm_websocket.py +1 -1
- GameSentenceMiner/web/static/css/shared.css +20 -0
- GameSentenceMiner/web/static/css/stats.css +496 -1
- GameSentenceMiner/web/static/js/anki_stats.js +87 -3
- GameSentenceMiner/web/static/js/shared.js +2 -49
- GameSentenceMiner/web/static/js/stats.js +274 -39
- GameSentenceMiner/web/templates/anki_stats.html +36 -0
- GameSentenceMiner/web/templates/index.html +1 -1
- GameSentenceMiner/web/templates/stats.html +35 -15
- GameSentenceMiner/web/texthooking_page.py +31 -8
- {gamesentenceminer-2.17.1.dist-info → gamesentenceminer-2.17.2.dist-info}/METADATA +1 -1
- {gamesentenceminer-2.17.1.dist-info → gamesentenceminer-2.17.2.dist-info}/RECORD +28 -28
- {gamesentenceminer-2.17.1.dist-info → gamesentenceminer-2.17.2.dist-info}/WHEEL +0 -0
- {gamesentenceminer-2.17.1.dist-info → gamesentenceminer-2.17.2.dist-info}/entry_points.txt +0 -0
- {gamesentenceminer-2.17.1.dist-info → gamesentenceminer-2.17.2.dist-info}/licenses/LICENSE +0 -0
- {gamesentenceminer-2.17.1.dist-info → gamesentenceminer-2.17.2.dist-info}/top_level.txt +0 -0
|
@@ -267,57 +267,3 @@ os.makedirs(os.path.dirname(TEXT_REPLACEMENTS_FILE), exist_ok=True)
|
|
|
267
267
|
# f.write(data)
|
|
268
268
|
# except Exception as e:
|
|
269
269
|
# logger.error(f"Failed to fetch JSON from {url}: {e}")
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
# Remove GitHub replacements from local OCR replacements file, these replacements are not needed
|
|
273
|
-
def remove_github_replacements_from_local_ocr():
|
|
274
|
-
github_url = "https://raw.githubusercontent.com/bpwhelan/GameSentenceMiner/main/electron-src/assets/ocr_replacements.json"
|
|
275
|
-
|
|
276
|
-
github_replacements = {}
|
|
277
|
-
try:
|
|
278
|
-
response = requests.get(github_url)
|
|
279
|
-
response.raise_for_status()
|
|
280
|
-
github_data = response.json()
|
|
281
|
-
github_replacements = github_data.get('args', {}).get('replacements', {})
|
|
282
|
-
logger.debug(f"Successfully fetched {len(github_replacements)} replacements from GitHub.")
|
|
283
|
-
except requests.exceptions.RequestException as e:
|
|
284
|
-
logger.debug(f"Failed to fetch GitHub replacements from {github_url}: {e}")
|
|
285
|
-
return
|
|
286
|
-
except json.JSONDecodeError as e:
|
|
287
|
-
logger.debug(f"Error decoding JSON from GitHub response: {e}")
|
|
288
|
-
return
|
|
289
|
-
|
|
290
|
-
if not os.path.exists(OCR_REPLACEMENTS_FILE):
|
|
291
|
-
logger.debug(f"Local file {OCR_REPLACEMENTS_FILE} does not exist. No replacements to remove.")
|
|
292
|
-
return
|
|
293
|
-
|
|
294
|
-
try:
|
|
295
|
-
with open(OCR_REPLACEMENTS_FILE, 'r', encoding='utf-8') as f:
|
|
296
|
-
local_ocr_data = json.load(f)
|
|
297
|
-
|
|
298
|
-
local_replacements = local_ocr_data.get('args', {}).get('replacements', {})
|
|
299
|
-
original_count = len(local_replacements)
|
|
300
|
-
logger.debug(f"Loaded {original_count} replacements from local file.")
|
|
301
|
-
|
|
302
|
-
removed_count = 0
|
|
303
|
-
for key_to_remove in github_replacements.keys():
|
|
304
|
-
if key_to_remove in local_replacements:
|
|
305
|
-
del local_replacements[key_to_remove]
|
|
306
|
-
removed_count += 1
|
|
307
|
-
|
|
308
|
-
if removed_count > 0:
|
|
309
|
-
local_ocr_data['args']['replacements'] = local_replacements
|
|
310
|
-
with open(OCR_REPLACEMENTS_FILE, 'w', encoding='utf-8') as f:
|
|
311
|
-
json.dump(local_ocr_data, f, ensure_ascii=False, indent=4)
|
|
312
|
-
logger.debug(f"Successfully removed {removed_count} replacements from {OCR_REPLACEMENTS_FILE}.")
|
|
313
|
-
logger.debug(f"Remaining replacements in local file: {len(local_replacements)}")
|
|
314
|
-
else:
|
|
315
|
-
logger.debug("No matching replacements from GitHub found in your local file to remove.")
|
|
316
|
-
|
|
317
|
-
except json.JSONDecodeError as e:
|
|
318
|
-
logger.debug(f"Error decoding JSON from {OCR_REPLACEMENTS_FILE}: {e}. Please ensure it's valid JSON.")
|
|
319
|
-
except Exception as e:
|
|
320
|
-
logger.debug(f"An unexpected error occurred while processing {OCR_REPLACEMENTS_FILE}: {e}")
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
remove_github_replacements_from_local_ocr()
|
|
@@ -795,9 +795,20 @@ def register_database_api_routes(app):
|
|
|
795
795
|
punctionation_regex = regex.compile(r'[\p{P}\p{S}\p{Z}]')
|
|
796
796
|
# Get optional year filter parameter
|
|
797
797
|
filter_year = request.args.get('year', None)
|
|
798
|
+
|
|
799
|
+
# Get Start and End time as unix timestamp
|
|
800
|
+
start_timestamp = request.args.get('start', None)
|
|
801
|
+
end_timestamp = request.args.get('end', None)
|
|
798
802
|
|
|
803
|
+
# Convert timestamps to float if provided
|
|
804
|
+
start_timestamp = float(start_timestamp) if start_timestamp else None
|
|
805
|
+
end_timestamp = float(end_timestamp) if end_timestamp else None
|
|
806
|
+
|
|
807
|
+
# # 1. Fetch all lines and sort them chronologically
|
|
808
|
+
# all_lines = sorted(GameLinesTable.all(), key=lambda line: line.timestamp)
|
|
809
|
+
|
|
799
810
|
# 1. Fetch all lines and sort them chronologically
|
|
800
|
-
all_lines =
|
|
811
|
+
all_lines = GameLinesTable.get_lines_filtered_by_timestamp(start=start_timestamp, end=end_timestamp)
|
|
801
812
|
|
|
802
813
|
if not all_lines:
|
|
803
814
|
return jsonify({"labels": [], "datasets": []})
|
|
@@ -78,7 +78,7 @@ class WebsocketServerThread(threading.Thread):
|
|
|
78
78
|
while True:
|
|
79
79
|
try:
|
|
80
80
|
self.server = start_server = websockets.serve(self.server_handler,
|
|
81
|
-
|
|
81
|
+
get_config().advanced.localhost_bind_address,
|
|
82
82
|
self.get_ws_port_func(),
|
|
83
83
|
max_size=1000000000)
|
|
84
84
|
async with start_server:
|
|
@@ -929,4 +929,24 @@ h1 {
|
|
|
929
929
|
.games-table td:nth-child(6) {
|
|
930
930
|
display: none;
|
|
931
931
|
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
input[type="date"].dashboard-date-input {
|
|
935
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
936
|
+
transition: all 0.2s ease; /* smooth animation */
|
|
937
|
+
border-radius: 8px;
|
|
938
|
+
border: 1px solid var(--border-color);
|
|
939
|
+
padding: 8px 12px;
|
|
940
|
+
font-size: 14px;
|
|
941
|
+
font-weight: 500;
|
|
942
|
+
color: var(--text-primary);
|
|
943
|
+
background: var(--bg-tertiary);
|
|
944
|
+
cursor: pointer;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
input[type="date"].dashboard-date-input:focus,
|
|
948
|
+
input[type="date"].dashboard-date-input:hover {
|
|
949
|
+
border-color: var(--accent-color);
|
|
950
|
+
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.15);
|
|
951
|
+
outline: none;
|
|
932
952
|
}
|
|
@@ -657,6 +657,440 @@
|
|
|
657
657
|
margin-bottom: 16px;
|
|
658
658
|
}
|
|
659
659
|
|
|
660
|
+
/* ================================
|
|
661
|
+
Dashboard Cards Styles
|
|
662
|
+
================================ */
|
|
663
|
+
.dashboard-container {
|
|
664
|
+
display: grid;
|
|
665
|
+
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
|
666
|
+
gap: 30px;
|
|
667
|
+
margin-bottom: 40px;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
.dashboard-card {
|
|
671
|
+
background: var(--bg-secondary);
|
|
672
|
+
border-radius: 12px;
|
|
673
|
+
box-shadow: 0 4px 16px var(--shadow-color);
|
|
674
|
+
border: 1px solid var(--border-color);
|
|
675
|
+
padding: 24px;
|
|
676
|
+
transition: all 0.3s ease;
|
|
677
|
+
position: relative;
|
|
678
|
+
overflow: hidden;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
.dashboard-card:hover {
|
|
682
|
+
transform: translateY(-2px);
|
|
683
|
+
box-shadow: 0 8px 24px var(--shadow-color);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
.dashboard-card::before {
|
|
687
|
+
content: '';
|
|
688
|
+
position: absolute;
|
|
689
|
+
top: 0;
|
|
690
|
+
left: 0;
|
|
691
|
+
right: 0;
|
|
692
|
+
height: 4px;
|
|
693
|
+
background: linear-gradient(90deg, var(--accent-color), var(--success-color));
|
|
694
|
+
border-radius: 12px 12px 0 0;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
.dashboard-card.current-game::before {
|
|
698
|
+
background: linear-gradient(90deg, var(--accent-color), var(--info-color));
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
.dashboard-card.all-games::before {
|
|
702
|
+
background: linear-gradient(90deg, var(--success-color), var(--warning-color));
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
.dashboard-card.date-range::before {
|
|
706
|
+
background: linear-gradient(90deg, var(--info-color), var(--accent-color));
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
.dashboard-card.date-range {
|
|
710
|
+
margin-bottom: 30px;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.dashboard-card-header {
|
|
714
|
+
display: flex;
|
|
715
|
+
align-items: center;
|
|
716
|
+
justify-content: space-between;
|
|
717
|
+
margin-bottom: 20px;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
.dashboard-card-title {
|
|
721
|
+
font-size: 20px;
|
|
722
|
+
font-weight: 600;
|
|
723
|
+
color: var(--text-primary);
|
|
724
|
+
margin: 0;
|
|
725
|
+
display: flex;
|
|
726
|
+
align-items: center;
|
|
727
|
+
gap: 10px;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
.dashboard-card-icon {
|
|
731
|
+
font-size: 24px;
|
|
732
|
+
opacity: 0.8;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
.dashboard-card-subtitle {
|
|
736
|
+
font-size: 14px;
|
|
737
|
+
color: var(--text-tertiary);
|
|
738
|
+
margin: 4px 0 0 0;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/* ================================
|
|
742
|
+
Stats Grid
|
|
743
|
+
================================ */
|
|
744
|
+
.dashboard-stats-grid {
|
|
745
|
+
display: grid;
|
|
746
|
+
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
|
747
|
+
gap: 16px;
|
|
748
|
+
margin-bottom: 20px;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
.dashboard-stat-item {
|
|
752
|
+
text-align: center;
|
|
753
|
+
padding: 12px;
|
|
754
|
+
background: var(--bg-tertiary);
|
|
755
|
+
border-radius: 8px;
|
|
756
|
+
transition: all 0.2s ease;
|
|
757
|
+
position: relative;
|
|
758
|
+
cursor: pointer;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
.dashboard-stat-item:hover {
|
|
762
|
+
background: var(--border-color);
|
|
763
|
+
transform: scale(1.02);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.dashboard-stat-value {
|
|
767
|
+
font-size: 24px;
|
|
768
|
+
font-weight: bold;
|
|
769
|
+
color: var(--text-primary);
|
|
770
|
+
margin-bottom: 4px;
|
|
771
|
+
display: block;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
.dashboard-stat-label {
|
|
775
|
+
font-size: 12px;
|
|
776
|
+
color: var(--text-tertiary);
|
|
777
|
+
text-transform: uppercase;
|
|
778
|
+
letter-spacing: 0.5px;
|
|
779
|
+
font-weight: 500;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/* ================================
|
|
783
|
+
Progress Section
|
|
784
|
+
================================ */
|
|
785
|
+
.dashboard-progress-section {
|
|
786
|
+
margin-top: 20px;
|
|
787
|
+
padding-top: 20px;
|
|
788
|
+
border-top: 1px solid var(--border-color);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
.dashboard-progress-title {
|
|
792
|
+
font-size: 14px;
|
|
793
|
+
font-weight: 600;
|
|
794
|
+
color: var(--text-secondary);
|
|
795
|
+
margin-bottom: 12px;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
.dashboard-progress-items {
|
|
799
|
+
display: flex;
|
|
800
|
+
justify-content: space-between;
|
|
801
|
+
gap: 16px;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.dashboard-progress-item {
|
|
805
|
+
text-align: center;
|
|
806
|
+
flex: 1;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
.dashboard-progress-value {
|
|
810
|
+
font-size: 18px;
|
|
811
|
+
font-weight: bold;
|
|
812
|
+
margin-bottom: 4px;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
.dashboard-progress-value.positive {
|
|
816
|
+
color: var(--success-color);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
.dashboard-progress-value.neutral {
|
|
820
|
+
color: var(--text-secondary);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
.dashboard-progress-label {
|
|
824
|
+
font-size: 11px;
|
|
825
|
+
color: var(--text-tertiary);
|
|
826
|
+
text-transform: uppercase;
|
|
827
|
+
letter-spacing: 0.5px;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/* ================================
|
|
831
|
+
Streak Indicator
|
|
832
|
+
================================ */
|
|
833
|
+
.dashboard-streak-indicator {
|
|
834
|
+
display: inline-flex;
|
|
835
|
+
align-items: center;
|
|
836
|
+
gap: 4px;
|
|
837
|
+
font-size: 12px;
|
|
838
|
+
color: var(--success-color);
|
|
839
|
+
background: rgba(40, 167, 69, 0.1);
|
|
840
|
+
padding: 4px 8px;
|
|
841
|
+
border-radius: 12px;
|
|
842
|
+
font-weight: 500;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
.dashboard-streak-indicator::before {
|
|
846
|
+
content: '🔥';
|
|
847
|
+
font-size: 14px;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/* ================================
|
|
851
|
+
Date Range Card
|
|
852
|
+
================================ */
|
|
853
|
+
.dashboard-date-range {
|
|
854
|
+
display: flex;
|
|
855
|
+
gap: 20px;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
.dashboard-date-item {
|
|
859
|
+
flex: 1;
|
|
860
|
+
display: flex;
|
|
861
|
+
flex-direction: column;
|
|
862
|
+
gap: 6px;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
.dashboard-date-item label {
|
|
866
|
+
font-size: 13px;
|
|
867
|
+
color: var(--text-secondary);
|
|
868
|
+
font-weight: 500;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
.dashboard-date-input {
|
|
872
|
+
padding: 8px 12px;
|
|
873
|
+
border: 1px solid var(--border-color);
|
|
874
|
+
border-radius: 8px;
|
|
875
|
+
background: var(--bg-tertiary);
|
|
876
|
+
color: var(--text-primary);
|
|
877
|
+
font-size: 14px;
|
|
878
|
+
transition: all 0.2s ease;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
.dashboard-date-input:focus {
|
|
882
|
+
outline: none;
|
|
883
|
+
border-color: var(--accent-color);
|
|
884
|
+
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.15);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/* ================================
|
|
888
|
+
Tooltip Styles
|
|
889
|
+
================================ */
|
|
890
|
+
.tooltip {
|
|
891
|
+
position: relative;
|
|
892
|
+
cursor: help;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
.tooltip::before {
|
|
896
|
+
content: attr(data-tooltip);
|
|
897
|
+
position: absolute;
|
|
898
|
+
bottom: 125%;
|
|
899
|
+
left: 50%;
|
|
900
|
+
transform: translateX(-50%);
|
|
901
|
+
background: rgba(0, 0, 0, 0.9);
|
|
902
|
+
color: white;
|
|
903
|
+
padding: 8px 12px;
|
|
904
|
+
border-radius: 6px;
|
|
905
|
+
font-size: 12px;
|
|
906
|
+
white-space: nowrap;
|
|
907
|
+
opacity: 0;
|
|
908
|
+
visibility: hidden;
|
|
909
|
+
transition: all 0.3s ease;
|
|
910
|
+
z-index: 1000;
|
|
911
|
+
pointer-events: none;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
.tooltip::after {
|
|
915
|
+
content: '';
|
|
916
|
+
position: absolute;
|
|
917
|
+
bottom: 120%;
|
|
918
|
+
left: 50%;
|
|
919
|
+
transform: translateX(-50%);
|
|
920
|
+
border: 4px solid transparent;
|
|
921
|
+
border-top-color: rgba(0, 0, 0, 0.9);
|
|
922
|
+
opacity: 0;
|
|
923
|
+
visibility: hidden;
|
|
924
|
+
transition: all 0.3s ease;
|
|
925
|
+
z-index: 1000;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
.tooltip:hover::before,
|
|
929
|
+
.tooltip:hover::after {
|
|
930
|
+
opacity: 1;
|
|
931
|
+
visibility: visible;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/* ================================
|
|
935
|
+
Loading State
|
|
936
|
+
================================ */
|
|
937
|
+
.dashboard-loading {
|
|
938
|
+
display: flex;
|
|
939
|
+
align-items: center;
|
|
940
|
+
justify-content: center;
|
|
941
|
+
min-height: 200px;
|
|
942
|
+
color: var(--text-tertiary);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
.dashboard-loading .spinner {
|
|
946
|
+
margin-right: 10px;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
/* ================================
|
|
950
|
+
Error State
|
|
951
|
+
================================ */
|
|
952
|
+
.dashboard-error {
|
|
953
|
+
text-align: center;
|
|
954
|
+
padding: 40px 20px;
|
|
955
|
+
color: var(--danger-color);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
.dashboard-error-icon {
|
|
959
|
+
font-size: 48px;
|
|
960
|
+
margin-bottom: 16px;
|
|
961
|
+
opacity: 0.7;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
.dashboard-error-message {
|
|
965
|
+
font-size: 16px;
|
|
966
|
+
margin-bottom: 16px;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
.dashboard-retry-btn {
|
|
970
|
+
background-color: var(--accent-color);
|
|
971
|
+
color: white;
|
|
972
|
+
border: none;
|
|
973
|
+
padding: 10px 20px;
|
|
974
|
+
border-radius: 6px;
|
|
975
|
+
cursor: pointer;
|
|
976
|
+
font-size: 14px;
|
|
977
|
+
transition: all 0.3s ease;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
.dashboard-retry-btn:hover {
|
|
981
|
+
background-color: #0056b3;
|
|
982
|
+
transform: translateY(-1px);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/* ================================
|
|
986
|
+
Popups
|
|
987
|
+
================================ */
|
|
988
|
+
.dashboard-popup,
|
|
989
|
+
.no-data-popup {
|
|
990
|
+
position: fixed;
|
|
991
|
+
top: 0;
|
|
992
|
+
left: 0;
|
|
993
|
+
right: 0;
|
|
994
|
+
bottom: 0;
|
|
995
|
+
display: flex;
|
|
996
|
+
align-items: center;
|
|
997
|
+
justify-content: center;
|
|
998
|
+
background: rgba(0, 0, 0, 0.4);
|
|
999
|
+
z-index: 2000;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
.hidden {
|
|
1003
|
+
display: none;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.dashboard-popup-content,
|
|
1007
|
+
.no-data-content {
|
|
1008
|
+
background: var(--bg-secondary);
|
|
1009
|
+
border: 1px solid var(--border-color);
|
|
1010
|
+
border-radius: 12px;
|
|
1011
|
+
padding: 24px;
|
|
1012
|
+
box-shadow: 0 8px 24px var(--shadow-color);
|
|
1013
|
+
text-align: center;
|
|
1014
|
+
max-width: 400px;
|
|
1015
|
+
width: 90%;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
.dashboard-popup-icon {
|
|
1019
|
+
font-size: 32px;
|
|
1020
|
+
margin-bottom: 12px;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
.dashboard-popup-message,
|
|
1024
|
+
.no-data-content p {
|
|
1025
|
+
font-size: 14px;
|
|
1026
|
+
color: var(--text-primary);
|
|
1027
|
+
margin-bottom: 20px;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
.dashboard-popup-btn,
|
|
1031
|
+
#closeNoDataPopup {
|
|
1032
|
+
background: var(--accent-color);
|
|
1033
|
+
color: white;
|
|
1034
|
+
border: none;
|
|
1035
|
+
padding: 10px 18px;
|
|
1036
|
+
border-radius: 8px;
|
|
1037
|
+
font-size: 14px;
|
|
1038
|
+
cursor: pointer;
|
|
1039
|
+
transition: all 0.2s ease;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
.dashboard-popup-btn:hover,
|
|
1043
|
+
#closeNoDataPopup:hover {
|
|
1044
|
+
background: #0056b3;
|
|
1045
|
+
transform: translateY(-1px);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
/* Popup box */
|
|
1049
|
+
.dashboard-popup-content {
|
|
1050
|
+
background: var(--bg-secondary);
|
|
1051
|
+
border-radius: 12px;
|
|
1052
|
+
box-shadow: 0 8px 24px var(--shadow-color);
|
|
1053
|
+
border: 1px solid var(--border-color);
|
|
1054
|
+
padding: 24px;
|
|
1055
|
+
max-width: 320px;
|
|
1056
|
+
text-align: center;
|
|
1057
|
+
animation: popupFadeIn 0.3s ease;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
.dashboard-popup-icon {
|
|
1061
|
+
font-size: 36px;
|
|
1062
|
+
margin-bottom: 12px;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
.dashboard-popup-message {
|
|
1066
|
+
font-size: 14px;
|
|
1067
|
+
color: var(--danger-color);
|
|
1068
|
+
margin-bottom: 20px;
|
|
1069
|
+
font-weight: 500;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
.dashboard-popup-btn {
|
|
1073
|
+
padding: 10px 16px;
|
|
1074
|
+
border-radius: 6px;
|
|
1075
|
+
border: none;
|
|
1076
|
+
background: var(--accent-color);
|
|
1077
|
+
color: #fff;
|
|
1078
|
+
font-size: 14px;
|
|
1079
|
+
font-weight: 600;
|
|
1080
|
+
cursor: pointer;
|
|
1081
|
+
transition: all 0.2s ease;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
.dashboard-popup-btn:hover {
|
|
1085
|
+
background: var(--accent-color-hover, #0056b3);
|
|
1086
|
+
transform: translateY(-1px);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
@keyframes popupFadeIn {
|
|
1090
|
+
from { transform: scale(0.95); opacity: 0; }
|
|
1091
|
+
to { transform: scale(1); opacity: 1; }
|
|
1092
|
+
}
|
|
1093
|
+
|
|
660
1094
|
/* Responsive Design for Goal Progress Chart */
|
|
661
1095
|
@media (max-width: 768px) {
|
|
662
1096
|
.goal-progress-grid {
|
|
@@ -739,4 +1173,65 @@
|
|
|
739
1173
|
margin-left: 0;
|
|
740
1174
|
align-self: center;
|
|
741
1175
|
}
|
|
742
|
-
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/* Responsive adjustments */
|
|
1179
|
+
@media (max-width: 768px) {
|
|
1180
|
+
.dashboard-date-range {
|
|
1181
|
+
flex-direction: column;
|
|
1182
|
+
gap: 12px;
|
|
1183
|
+
padding: 12px 16px;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
.dashboard-date-item {
|
|
1187
|
+
width: 100%;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
.dashboard-fetch-btn {
|
|
1191
|
+
width: 100%;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
.no-data-popup {
|
|
1197
|
+
position: fixed;
|
|
1198
|
+
inset: 0;
|
|
1199
|
+
background: rgba(0,0,0,0.6);
|
|
1200
|
+
display: flex;
|
|
1201
|
+
justify-content: center;
|
|
1202
|
+
align-items: center;
|
|
1203
|
+
z-index: 2000;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
.no-data-popup.hidden {
|
|
1207
|
+
display: none;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
.no-data-content {
|
|
1211
|
+
background: var(--bg-secondary);
|
|
1212
|
+
padding: 20px 30px;
|
|
1213
|
+
border-radius: 10px;
|
|
1214
|
+
text-align: center;
|
|
1215
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
.no-data-content p {
|
|
1219
|
+
margin-bottom: 16px;
|
|
1220
|
+
color: var(--text-primary);
|
|
1221
|
+
font-size: 15px;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
.no-data-content button {
|
|
1225
|
+
padding: 8px 16px;
|
|
1226
|
+
background: var(--accent-color);
|
|
1227
|
+
border: none;
|
|
1228
|
+
border-radius: 6px;
|
|
1229
|
+
color: #fff;
|
|
1230
|
+
font-weight: 600;
|
|
1231
|
+
cursor: pointer;
|
|
1232
|
+
transition: all 0.2s ease;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
.no-data-content button:hover {
|
|
1236
|
+
background: #0056b3;
|
|
1237
|
+
}
|