1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

fix: apply theme on the fly in preferences, theme-store refactoring

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-07-23 18:26:16 +03:00
parent 6fd9b7cf76
commit 407c4fb4d0
15 changed files with 322 additions and 315 deletions

View File

@ -116,11 +116,11 @@ msgstr "Add field"
#~ msgid "Added repos" #~ msgid "Added repos"
#~ msgstr "Added repos" #~ msgstr "Added repos"
#: src/renderer/components/+preferences/preferences.tsx:149 #: src/renderer/components/+preferences/preferences.tsx:147
msgid "Added repos:" msgid "Added repos:"
msgstr "Added repos:" msgstr "Added repos:"
#: src/renderer/components/+preferences/preferences.tsx:108 #: src/renderer/components/+preferences/preferences.tsx:106
msgid "Adding helm branch <0>{0}</0> has failed: {1}" msgid "Adding helm branch <0>{0}</0> has failed: {1}"
msgstr "Adding helm branch <0>{0}</0> has failed: {1}" msgstr "Adding helm branch <0>{0}</0> has failed: {1}"
@ -202,11 +202,11 @@ msgstr "Allocatable"
msgid "Allow Privilege Escalation" msgid "Allow Privilege Escalation"
msgstr "Allow Privilege Escalation" msgstr "Allow Privilege Escalation"
#: src/renderer/components/+preferences/preferences.tsx:177 #: src/renderer/components/+preferences/preferences.tsx:175
msgid "Allow telemetry & usage tracking" msgid "Allow telemetry & usage tracking"
msgstr "Allow telemetry & usage tracking" msgstr "Allow telemetry & usage tracking"
#: src/renderer/components/+preferences/preferences.tsx:169 #: src/renderer/components/+preferences/preferences.tsx:167
msgid "Allow untrusted Certificate Authorities" msgid "Allow untrusted Certificate Authorities"
msgstr "Allow untrusted Certificate Authorities" msgstr "Allow untrusted Certificate Authorities"
@ -401,7 +401,7 @@ msgstr "Cancel"
msgid "Capacity" msgid "Capacity"
msgstr "Capacity" msgstr "Capacity"
#: src/renderer/components/+preferences/preferences.tsx:168 #: src/renderer/components/+preferences/preferences.tsx:166
msgid "Certificate Trust" msgid "Certificate Trust"
msgstr "Certificate Trust" msgstr "Certificate Trust"
@ -468,7 +468,7 @@ msgstr "Cluster IP"
msgid "Cluster Issuers" msgid "Cluster Issuers"
msgstr "Cluster Issuers" msgstr "Cluster Issuers"
#: src/renderer/components/+preferences/preferences.tsx:139 #: src/renderer/components/+preferences/preferences.tsx:137
msgid "Color Theme" msgid "Color Theme"
msgstr "Color Theme" msgstr "Color Theme"
@ -717,7 +717,7 @@ msgstr "Daemon Sets"
msgid "DaemonSets" msgid "DaemonSets"
msgstr "DaemonSets" msgstr "DaemonSets"
#: src/renderer/components/+preferences/preferences.tsx:40 #: src/renderer/theme.store.ts:32
msgid "Dark" msgid "Dark"
msgstr "Dark" msgstr "Dark"
@ -780,7 +780,7 @@ msgstr "Disk"
msgid "Disk:" msgid "Disk:"
msgstr "Disk:" msgstr "Disk:"
#: src/renderer/components/+preferences/preferences.tsx:173 #: src/renderer/components/+preferences/preferences.tsx:171
msgid "Does not affect cluster communications!" msgid "Does not affect cluster communications!"
msgstr "Does not affect cluster communications!" msgstr "Does not affect cluster communications!"
@ -788,7 +788,7 @@ msgstr "Does not affect cluster communications!"
msgid "Domains" msgid "Domains"
msgstr "Domains" msgstr "Domains"
#: src/renderer/components/+preferences/preferences.tsx:142 #: src/renderer/components/+preferences/preferences.tsx:140
msgid "Download Mirror" msgid "Download Mirror"
msgstr "Download Mirror" msgstr "Download Mirror"
@ -796,7 +796,7 @@ msgstr "Download Mirror"
msgid "Download file" msgid "Download file"
msgstr "Download file" msgstr "Download file"
#: src/renderer/components/+preferences/preferences.tsx:143 #: src/renderer/components/+preferences/preferences.tsx:141
msgid "Download mirror for kubectl" msgid "Download mirror for kubectl"
msgstr "Download mirror for kubectl" msgstr "Download mirror for kubectl"
@ -967,7 +967,7 @@ msgstr "Groups"
msgid "HPA" msgid "HPA"
msgstr "HPA" msgstr "HPA"
#: src/renderer/components/+preferences/preferences.tsx:162 #: src/renderer/components/+preferences/preferences.tsx:160
msgid "HTTP Proxy" msgid "HTTP Proxy"
msgstr "HTTP Proxy" msgstr "HTTP Proxy"
@ -975,7 +975,7 @@ msgstr "HTTP Proxy"
msgid "HTTP Proxy server. Used for communicating with Kubernetes API." msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
msgstr "HTTP Proxy server. Used for communicating with Kubernetes API." msgstr "HTTP Proxy server. Used for communicating with Kubernetes API."
#: src/renderer/components/+preferences/preferences.tsx:145 #: src/renderer/components/+preferences/preferences.tsx:143
msgid "Helm" msgid "Helm"
msgstr "Helm" msgstr "Helm"
@ -995,7 +995,7 @@ msgstr "Helm Install: {repo}/{name}"
msgid "Helm Upgrade: {0}" msgid "Helm Upgrade: {0}"
msgstr "Helm Upgrade: {0}" msgstr "Helm Upgrade: {0}"
#: src/renderer/components/+preferences/preferences.tsx:61 #: src/renderer/components/+preferences/preferences.tsx:50
msgid "Helm branch <0>{0}</0> already in use" msgid "Helm branch <0>{0}</0> already in use"
msgstr "Helm branch <0>{0}</0> already in use" msgstr "Helm branch <0>{0}</0> already in use"
@ -1209,7 +1209,7 @@ msgstr "Last seen"
msgid "Last transition time: {lastTransitionTime}" msgid "Last transition time: {lastTransitionTime}"
msgstr "Last transition time: {lastTransitionTime}" msgstr "Last transition time: {lastTransitionTime}"
#: src/renderer/components/+preferences/preferences.tsx:131 #: src/renderer/components/+preferences/preferences.tsx:129
msgid "Lens Global Settings" msgid "Lens Global Settings"
msgstr "Lens Global Settings" msgstr "Lens Global Settings"
@ -1217,7 +1217,7 @@ msgstr "Lens Global Settings"
msgid "Level" msgid "Level"
msgstr "Level" msgstr "Level"
#: src/renderer/components/+preferences/preferences.tsx:41 #: src/renderer/theme.store.ts:33
msgid "Light" msgid "Light"
msgstr "Light" msgstr "Light"
@ -1485,7 +1485,7 @@ msgstr "Namespaces"
msgid "Namespaces: {0}" msgid "Namespaces: {0}"
msgstr "Namespaces: {0}" msgstr "Namespaces: {0}"
#: src/renderer/components/+preferences/preferences.tsx:172 #: src/renderer/components/+preferences/preferences.tsx:170
msgid "Needed with some corporate proxies that do certificate re-writing." msgid "Needed with some corporate proxies that do certificate re-writing."
msgstr "Needed with some corporate proxies that do certificate re-writing." msgstr "Needed with some corporate proxies that do certificate re-writing."
@ -1755,7 +1755,7 @@ msgstr "Port"
msgid "Ports" msgid "Ports"
msgstr "Ports" msgstr "Ports"
#: src/renderer/components/+preferences/preferences.tsx:126 #: src/renderer/components/+preferences/preferences.tsx:124
msgid "Preferences" msgid "Preferences"
msgstr "Preferences" msgstr "Preferences"
@ -1777,7 +1777,7 @@ msgstr "Privileged"
msgid "Provisioner" msgid "Provisioner"
msgstr "Provisioner" msgstr "Provisioner"
#: src/renderer/components/+preferences/preferences.tsx:165 #: src/renderer/components/+preferences/preferences.tsx:163
msgid "Proxy is used only for non-cluster communication." msgid "Proxy is used only for non-cluster communication."
msgstr "Proxy is used only for non-cluster communication." msgstr "Proxy is used only for non-cluster communication."
@ -1861,7 +1861,7 @@ msgstr "Release: {0}"
msgid "Releases" msgid "Releases"
msgstr "Releases" msgstr "Releases"
#: src/renderer/components/+preferences/preferences.tsx:156 #: src/renderer/components/+preferences/preferences.tsx:154
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60 #: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:60 #: src/renderer/components/cluster-manager/clusters-menu.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:64 #: src/renderer/components/cluster-manager/clusters-menu.tsx:64
@ -1903,7 +1903,7 @@ msgstr "Remove selected items ({0})"
msgid "Remove {resourceKind} <0>{resourceName}</0>?" msgid "Remove {resourceKind} <0>{resourceName}</0>?"
msgstr "Remove {resourceKind} <0>{resourceName}</0>?" msgstr "Remove {resourceKind} <0>{resourceName}</0>?"
#: src/renderer/components/+preferences/preferences.tsx:119 #: src/renderer/components/+preferences/preferences.tsx:117
msgid "Removing helm branch <0>{0}</0> has failed: {1}" msgid "Removing helm branch <0>{0}</0> has failed: {1}"
msgstr "Removing helm branch <0>{0}</0> has failed: {1}" msgstr "Removing helm branch <0>{0}</0> has failed: {1}"
@ -1927,7 +1927,7 @@ msgstr "Replicas"
msgid "Repo/Name" msgid "Repo/Name"
msgstr "Repo/Name" msgstr "Repo/Name"
#: src/renderer/components/+preferences/preferences.tsx:146 #: src/renderer/components/+preferences/preferences.tsx:144
msgid "Repositories" msgid "Repositories"
msgstr "Repositories" msgstr "Repositories"
@ -2378,11 +2378,11 @@ msgstr "TLS"
msgid "Taints" msgid "Taints"
msgstr "Taints" msgstr "Taints"
#: src/renderer/components/+preferences/preferences.tsx:176 #: src/renderer/components/+preferences/preferences.tsx:174
msgid "Telemetry & Usage Tracking" msgid "Telemetry & Usage Tracking"
msgstr "Telemetry & Usage Tracking" msgstr "Telemetry & Usage Tracking"
#: src/renderer/components/+preferences/preferences.tsx:179 #: src/renderer/components/+preferences/preferences.tsx:177
msgid "Telemetry & usage data is collected to continuously improve the Lens experience." msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
msgstr "Telemetry & usage data is collected to continuously improve the Lens experience." msgstr "Telemetry & usage data is collected to continuously improve the Lens experience."
@ -2414,7 +2414,7 @@ msgstr "This field must contain only lowercase latin characters, numbers and das
msgid "This is the quick launch menu." msgid "This is the quick launch menu."
msgstr "This is the quick launch menu." msgstr "This is the quick launch menu."
#: src/renderer/components/+preferences/preferences.tsx:171 #: src/renderer/components/+preferences/preferences.tsx:169
msgid "This will make Lens to trust ANY certificate authority without any validations." msgid "This will make Lens to trust ANY certificate authority without any validations."
msgstr "This will make Lens to trust ANY certificate authority without any validations." msgstr "This will make Lens to trust ANY certificate authority without any validations."
@ -2457,7 +2457,7 @@ msgstr "Transmit"
msgid "Type" msgid "Type"
msgstr "Type" msgstr "Type"
#: src/renderer/components/+preferences/preferences.tsx:163 #: src/renderer/components/+preferences/preferences.tsx:161
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)" msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
msgstr "Type HTTP proxy url (example: http://proxy.acme.org:8080)" msgstr "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
@ -2650,7 +2650,7 @@ msgstr "ago"
msgid "and <0>{tailCount}</0> more" msgid "and <0>{tailCount}</0> more"
msgstr "and <0>{tailCount}</0> more" msgstr "and <0>{tailCount}</0> more"
#: src/renderer/components/+preferences/preferences.tsx:131 #: src/renderer/components/+preferences/preferences.tsx:129
msgid "applicable to all clusters" msgid "applicable to all clusters"
msgstr "applicable to all clusters" msgstr "applicable to all clusters"

View File

@ -116,11 +116,11 @@ msgstr ""
#~ msgid "Added repos" #~ msgid "Added repos"
#~ msgstr "" #~ msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:149 #: src/renderer/components/+preferences/preferences.tsx:147
msgid "Added repos:" msgid "Added repos:"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:108 #: src/renderer/components/+preferences/preferences.tsx:106
msgid "Adding helm branch <0>{0}</0> has failed: {1}" msgid "Adding helm branch <0>{0}</0> has failed: {1}"
msgstr "" msgstr ""
@ -202,11 +202,11 @@ msgstr ""
msgid "Allow Privilege Escalation" msgid "Allow Privilege Escalation"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:177 #: src/renderer/components/+preferences/preferences.tsx:175
msgid "Allow telemetry & usage tracking" msgid "Allow telemetry & usage tracking"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:169 #: src/renderer/components/+preferences/preferences.tsx:167
msgid "Allow untrusted Certificate Authorities" msgid "Allow untrusted Certificate Authorities"
msgstr "" msgstr ""
@ -401,7 +401,7 @@ msgstr ""
msgid "Capacity" msgid "Capacity"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:168 #: src/renderer/components/+preferences/preferences.tsx:166
msgid "Certificate Trust" msgid "Certificate Trust"
msgstr "" msgstr ""
@ -464,7 +464,7 @@ msgstr ""
msgid "Cluster Issuers" msgid "Cluster Issuers"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:139 #: src/renderer/components/+preferences/preferences.tsx:137
msgid "Color Theme" msgid "Color Theme"
msgstr "" msgstr ""
@ -713,7 +713,7 @@ msgstr ""
msgid "DaemonSets" msgid "DaemonSets"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:40 #: src/renderer/theme.store.ts:32
msgid "Dark" msgid "Dark"
msgstr "" msgstr ""
@ -776,7 +776,7 @@ msgstr ""
msgid "Disk:" msgid "Disk:"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:173 #: src/renderer/components/+preferences/preferences.tsx:171
msgid "Does not affect cluster communications!" msgid "Does not affect cluster communications!"
msgstr "" msgstr ""
@ -784,7 +784,7 @@ msgstr ""
msgid "Domains" msgid "Domains"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:142 #: src/renderer/components/+preferences/preferences.tsx:140
msgid "Download Mirror" msgid "Download Mirror"
msgstr "" msgstr ""
@ -792,7 +792,7 @@ msgstr ""
msgid "Download file" msgid "Download file"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:143 #: src/renderer/components/+preferences/preferences.tsx:141
msgid "Download mirror for kubectl" msgid "Download mirror for kubectl"
msgstr "" msgstr ""
@ -958,7 +958,7 @@ msgstr ""
msgid "HPA" msgid "HPA"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:162 #: src/renderer/components/+preferences/preferences.tsx:160
msgid "HTTP Proxy" msgid "HTTP Proxy"
msgstr "" msgstr ""
@ -966,7 +966,7 @@ msgstr ""
msgid "HTTP Proxy server. Used for communicating with Kubernetes API." msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:145 #: src/renderer/components/+preferences/preferences.tsx:143
msgid "Helm" msgid "Helm"
msgstr "" msgstr ""
@ -986,7 +986,7 @@ msgstr ""
msgid "Helm Upgrade: {0}" msgid "Helm Upgrade: {0}"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:61 #: src/renderer/components/+preferences/preferences.tsx:50
msgid "Helm branch <0>{0}</0> already in use" msgid "Helm branch <0>{0}</0> already in use"
msgstr "" msgstr ""
@ -1200,7 +1200,7 @@ msgstr ""
msgid "Last transition time: {lastTransitionTime}" msgid "Last transition time: {lastTransitionTime}"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:131 #: src/renderer/components/+preferences/preferences.tsx:129
msgid "Lens Global Settings" msgid "Lens Global Settings"
msgstr "" msgstr ""
@ -1208,7 +1208,7 @@ msgstr ""
msgid "Level" msgid "Level"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:41 #: src/renderer/theme.store.ts:33
msgid "Light" msgid "Light"
msgstr "" msgstr ""
@ -1476,7 +1476,7 @@ msgstr ""
msgid "Namespaces: {0}" msgid "Namespaces: {0}"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:172 #: src/renderer/components/+preferences/preferences.tsx:170
msgid "Needed with some corporate proxies that do certificate re-writing." msgid "Needed with some corporate proxies that do certificate re-writing."
msgstr "" msgstr ""
@ -1738,7 +1738,7 @@ msgstr ""
msgid "Ports" msgid "Ports"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:126 #: src/renderer/components/+preferences/preferences.tsx:124
msgid "Preferences" msgid "Preferences"
msgstr "" msgstr ""
@ -1760,7 +1760,7 @@ msgstr ""
msgid "Provisioner" msgid "Provisioner"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:165 #: src/renderer/components/+preferences/preferences.tsx:163
msgid "Proxy is used only for non-cluster communication." msgid "Proxy is used only for non-cluster communication."
msgstr "" msgstr ""
@ -1844,7 +1844,7 @@ msgstr ""
msgid "Releases" msgid "Releases"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:156 #: src/renderer/components/+preferences/preferences.tsx:154
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60 #: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:60 #: src/renderer/components/cluster-manager/clusters-menu.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:64 #: src/renderer/components/cluster-manager/clusters-menu.tsx:64
@ -1886,7 +1886,7 @@ msgstr ""
msgid "Remove {resourceKind} <0>{resourceName}</0>?" msgid "Remove {resourceKind} <0>{resourceName}</0>?"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:119 #: src/renderer/components/+preferences/preferences.tsx:117
msgid "Removing helm branch <0>{0}</0> has failed: {1}" msgid "Removing helm branch <0>{0}</0> has failed: {1}"
msgstr "" msgstr ""
@ -1910,7 +1910,7 @@ msgstr ""
msgid "Repo/Name" msgid "Repo/Name"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:146 #: src/renderer/components/+preferences/preferences.tsx:144
msgid "Repositories" msgid "Repositories"
msgstr "" msgstr ""
@ -2361,11 +2361,11 @@ msgstr ""
msgid "Taints" msgid "Taints"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:176 #: src/renderer/components/+preferences/preferences.tsx:174
msgid "Telemetry & Usage Tracking" msgid "Telemetry & Usage Tracking"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:179 #: src/renderer/components/+preferences/preferences.tsx:177
msgid "Telemetry & usage data is collected to continuously improve the Lens experience." msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
msgstr "" msgstr ""
@ -2397,7 +2397,7 @@ msgstr ""
msgid "This is the quick launch menu." msgid "This is the quick launch menu."
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:171 #: src/renderer/components/+preferences/preferences.tsx:169
msgid "This will make Lens to trust ANY certificate authority without any validations." msgid "This will make Lens to trust ANY certificate authority without any validations."
msgstr "" msgstr ""
@ -2440,7 +2440,7 @@ msgstr ""
msgid "Type" msgid "Type"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:163 #: src/renderer/components/+preferences/preferences.tsx:161
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)" msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
msgstr "" msgstr ""
@ -2633,7 +2633,7 @@ msgstr ""
msgid "and <0>{tailCount}</0> more" msgid "and <0>{tailCount}</0> more"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:131 #: src/renderer/components/+preferences/preferences.tsx:129
msgid "applicable to all clusters" msgid "applicable to all clusters"
msgstr "" msgstr ""

View File

@ -117,11 +117,11 @@ msgstr "Добавить поле"
#~ msgid "Added repos" #~ msgid "Added repos"
#~ msgstr "" #~ msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:149 #: src/renderer/components/+preferences/preferences.tsx:147
msgid "Added repos:" msgid "Added repos:"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:108 #: src/renderer/components/+preferences/preferences.tsx:106
msgid "Adding helm branch <0>{0}</0> has failed: {1}" msgid "Adding helm branch <0>{0}</0> has failed: {1}"
msgstr "" msgstr ""
@ -203,11 +203,11 @@ msgstr ""
msgid "Allow Privilege Escalation" msgid "Allow Privilege Escalation"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:177 #: src/renderer/components/+preferences/preferences.tsx:175
msgid "Allow telemetry & usage tracking" msgid "Allow telemetry & usage tracking"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:169 #: src/renderer/components/+preferences/preferences.tsx:167
msgid "Allow untrusted Certificate Authorities" msgid "Allow untrusted Certificate Authorities"
msgstr "" msgstr ""
@ -402,7 +402,7 @@ msgstr "Отмена"
msgid "Capacity" msgid "Capacity"
msgstr "Емкость" msgstr "Емкость"
#: src/renderer/components/+preferences/preferences.tsx:168 #: src/renderer/components/+preferences/preferences.tsx:166
msgid "Certificate Trust" msgid "Certificate Trust"
msgstr "" msgstr ""
@ -469,7 +469,7 @@ msgstr "IP-адрес кластера"
msgid "Cluster Issuers" msgid "Cluster Issuers"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:139 #: src/renderer/components/+preferences/preferences.tsx:137
msgid "Color Theme" msgid "Color Theme"
msgstr "" msgstr ""
@ -718,7 +718,7 @@ msgstr ""
msgid "DaemonSets" msgid "DaemonSets"
msgstr "DaemonSets" msgstr "DaemonSets"
#: src/renderer/components/+preferences/preferences.tsx:40 #: src/renderer/theme.store.ts:32
msgid "Dark" msgid "Dark"
msgstr "" msgstr ""
@ -781,7 +781,7 @@ msgstr "Диск"
msgid "Disk:" msgid "Disk:"
msgstr "Диск:" msgstr "Диск:"
#: src/renderer/components/+preferences/preferences.tsx:173 #: src/renderer/components/+preferences/preferences.tsx:171
msgid "Does not affect cluster communications!" msgid "Does not affect cluster communications!"
msgstr "" msgstr ""
@ -789,7 +789,7 @@ msgstr ""
msgid "Domains" msgid "Domains"
msgstr "Домены" msgstr "Домены"
#: src/renderer/components/+preferences/preferences.tsx:142 #: src/renderer/components/+preferences/preferences.tsx:140
msgid "Download Mirror" msgid "Download Mirror"
msgstr "" msgstr ""
@ -797,7 +797,7 @@ msgstr ""
msgid "Download file" msgid "Download file"
msgstr "Скачать файл" msgstr "Скачать файл"
#: src/renderer/components/+preferences/preferences.tsx:143 #: src/renderer/components/+preferences/preferences.tsx:141
msgid "Download mirror for kubectl" msgid "Download mirror for kubectl"
msgstr "" msgstr ""
@ -968,7 +968,7 @@ msgstr "Группы"
msgid "HPA" msgid "HPA"
msgstr "HPA" msgstr "HPA"
#: src/renderer/components/+preferences/preferences.tsx:162 #: src/renderer/components/+preferences/preferences.tsx:160
msgid "HTTP Proxy" msgid "HTTP Proxy"
msgstr "" msgstr ""
@ -976,7 +976,7 @@ msgstr ""
msgid "HTTP Proxy server. Used for communicating with Kubernetes API." msgid "HTTP Proxy server. Used for communicating with Kubernetes API."
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:145 #: src/renderer/components/+preferences/preferences.tsx:143
msgid "Helm" msgid "Helm"
msgstr "" msgstr ""
@ -996,7 +996,7 @@ msgstr "Helm установка: {repo}/{name}"
msgid "Helm Upgrade: {0}" msgid "Helm Upgrade: {0}"
msgstr "Helm обновление: {0}" msgstr "Helm обновление: {0}"
#: src/renderer/components/+preferences/preferences.tsx:61 #: src/renderer/components/+preferences/preferences.tsx:50
msgid "Helm branch <0>{0}</0> already in use" msgid "Helm branch <0>{0}</0> already in use"
msgstr "" msgstr ""
@ -1210,7 +1210,7 @@ msgstr "Увиденно в последний раз"
msgid "Last transition time: {lastTransitionTime}" msgid "Last transition time: {lastTransitionTime}"
msgstr "Последнее изменение: {lastTransitionTime}" msgstr "Последнее изменение: {lastTransitionTime}"
#: src/renderer/components/+preferences/preferences.tsx:131 #: src/renderer/components/+preferences/preferences.tsx:129
msgid "Lens Global Settings" msgid "Lens Global Settings"
msgstr "" msgstr ""
@ -1218,7 +1218,7 @@ msgstr ""
msgid "Level" msgid "Level"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:41 #: src/renderer/theme.store.ts:33
msgid "Light" msgid "Light"
msgstr "" msgstr ""
@ -1486,7 +1486,7 @@ msgstr "Namespaces"
msgid "Namespaces: {0}" msgid "Namespaces: {0}"
msgstr "Namespaces: {0}" msgstr "Namespaces: {0}"
#: src/renderer/components/+preferences/preferences.tsx:172 #: src/renderer/components/+preferences/preferences.tsx:170
msgid "Needed with some corporate proxies that do certificate re-writing." msgid "Needed with some corporate proxies that do certificate re-writing."
msgstr "" msgstr ""
@ -1756,7 +1756,7 @@ msgstr ""
msgid "Ports" msgid "Ports"
msgstr "Порты" msgstr "Порты"
#: src/renderer/components/+preferences/preferences.tsx:126 #: src/renderer/components/+preferences/preferences.tsx:124
msgid "Preferences" msgid "Preferences"
msgstr "" msgstr ""
@ -1778,7 +1778,7 @@ msgstr ""
msgid "Provisioner" msgid "Provisioner"
msgstr "Комиссия" msgstr "Комиссия"
#: src/renderer/components/+preferences/preferences.tsx:165 #: src/renderer/components/+preferences/preferences.tsx:163
msgid "Proxy is used only for non-cluster communication." msgid "Proxy is used only for non-cluster communication."
msgstr "" msgstr ""
@ -1862,7 +1862,7 @@ msgstr "Установка: {0}"
msgid "Releases" msgid "Releases"
msgstr "Релизы" msgstr "Релизы"
#: src/renderer/components/+preferences/preferences.tsx:156 #: src/renderer/components/+preferences/preferences.tsx:154
#: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60 #: src/renderer/components/+user-management-roles-bindings/role-binding-details.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:60 #: src/renderer/components/cluster-manager/clusters-menu.tsx:60
#: src/renderer/components/cluster-manager/clusters-menu.tsx:64 #: src/renderer/components/cluster-manager/clusters-menu.tsx:64
@ -1904,7 +1904,7 @@ msgstr "Удалить выбранные элементы ({0})"
msgid "Remove {resourceKind} <0>{resourceName}</0>?" msgid "Remove {resourceKind} <0>{resourceName}</0>?"
msgstr "Удалить {resourceKind} <0>{resourceName}</0>?" msgstr "Удалить {resourceKind} <0>{resourceName}</0>?"
#: src/renderer/components/+preferences/preferences.tsx:119 #: src/renderer/components/+preferences/preferences.tsx:117
msgid "Removing helm branch <0>{0}</0> has failed: {1}" msgid "Removing helm branch <0>{0}</0> has failed: {1}"
msgstr "" msgstr ""
@ -1928,7 +1928,7 @@ msgstr "Реплики"
msgid "Repo/Name" msgid "Repo/Name"
msgstr "Репозиторий/Имя" msgstr "Репозиторий/Имя"
#: src/renderer/components/+preferences/preferences.tsx:146 #: src/renderer/components/+preferences/preferences.tsx:144
msgid "Repositories" msgid "Repositories"
msgstr "" msgstr ""
@ -2379,11 +2379,11 @@ msgstr "TLS"
msgid "Taints" msgid "Taints"
msgstr "Метки блокировки" msgstr "Метки блокировки"
#: src/renderer/components/+preferences/preferences.tsx:176 #: src/renderer/components/+preferences/preferences.tsx:174
msgid "Telemetry & Usage Tracking" msgid "Telemetry & Usage Tracking"
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:179 #: src/renderer/components/+preferences/preferences.tsx:177
msgid "Telemetry & usage data is collected to continuously improve the Lens experience." msgid "Telemetry & usage data is collected to continuously improve the Lens experience."
msgstr "" msgstr ""
@ -2415,7 +2415,7 @@ msgstr "Это поле может содержать только латинс
msgid "This is the quick launch menu." msgid "This is the quick launch menu."
msgstr "" msgstr ""
#: src/renderer/components/+preferences/preferences.tsx:171 #: src/renderer/components/+preferences/preferences.tsx:169
msgid "This will make Lens to trust ANY certificate authority without any validations." msgid "This will make Lens to trust ANY certificate authority without any validations."
msgstr "" msgstr ""
@ -2458,7 +2458,7 @@ msgstr "Транзит"
msgid "Type" msgid "Type"
msgstr "Тип" msgstr "Тип"
#: src/renderer/components/+preferences/preferences.tsx:163 #: src/renderer/components/+preferences/preferences.tsx:161
msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)" msgid "Type HTTP proxy url (example: http://proxy.acme.org:8080)"
msgstr "" msgstr ""
@ -2651,7 +2651,7 @@ msgstr "тому назад"
msgid "and <0>{tailCount}</0> more" msgid "and <0>{tailCount}</0> more"
msgstr "и <0>{tailCount}</0> ещё" msgstr "и <0>{tailCount}</0> ещё"
#: src/renderer/components/+preferences/preferences.tsx:131 #: src/renderer/components/+preferences/preferences.tsx:129
msgid "applicable to all clusters" msgid "applicable to all clusters"
msgstr "" msgstr ""

View File

@ -1,3 +1,4 @@
import type { ThemeId } from "../renderer/theme.store";
import semver from "semver" import semver from "semver"
import { action, observable, reaction, toJS } from "mobx"; import { action, observable, reaction, toJS } from "mobx";
import { BaseStore } from "./base-store"; import { BaseStore } from "./base-store";
@ -5,20 +6,8 @@ import migrations from "../migrations/user-store"
import { getAppVersion } from "./utils/app-version"; import { getAppVersion } from "./utils/app-version";
import { tracker } from "./tracker"; import { tracker } from "./tracker";
// todo: merge with config.store.ts + theme.store.ts
// fixme: detect new contexts from .kube/config since last open // fixme: detect new contexts from .kube/config since last open
export enum ThemeType {
LIGHT = "light",
DARK = "dark",
}
export interface Theme {
name: string;
type: ThemeType;
colors?: Record<string, string>;
}
export interface UserStoreModel { export interface UserStoreModel {
lastSeenAppVersion: string; lastSeenAppVersion: string;
seenContexts: string[]; seenContexts: string[];
@ -27,13 +16,15 @@ export interface UserStoreModel {
export interface UserPreferences { export interface UserPreferences {
httpsProxy?: string; httpsProxy?: string;
colorTheme?: string | "dark" | "light"; colorTheme?: string;
allowUntrustedCAs?: boolean; allowUntrustedCAs?: boolean;
allowTelemetry?: boolean; allowTelemetry?: boolean;
downloadMirror?: string | "default"; downloadMirror?: string | "default";
} }
export class UserStore extends BaseStore<UserStoreModel> { export class UserStore extends BaseStore<UserStoreModel> {
static readonly defaultTheme: ThemeId = "kontena-dark"
private constructor() { private constructor() {
super({ super({
// configName: "lens-user-store", // todo: migrate from default filename // configName: "lens-user-store", // todo: migrate from default filename
@ -53,7 +44,7 @@ export class UserStore extends BaseStore<UserStoreModel> {
@observable preferences: UserPreferences = { @observable preferences: UserPreferences = {
allowTelemetry: true, allowTelemetry: true,
allowUntrustedCAs: false, allowUntrustedCAs: false,
colorTheme: "dark", colorTheme: UserStore.defaultTheme,
downloadMirror: "default", downloadMirror: "default",
httpsProxy: "", httpsProxy: "",
}; };
@ -62,6 +53,11 @@ export class UserStore extends BaseStore<UserStoreModel> {
return semver.gt(getAppVersion(), this.lastSeenAppVersion); return semver.gt(getAppVersion(), this.lastSeenAppVersion);
} }
@action
resetTheme() {
this.preferences.colorTheme = UserStore.defaultTheme;
}
@action @action
saveLastSeenAppVersion() { saveLastSeenAppVersion() {
tracker.event("app", "whats-new-seen") tracker.event("app", "whats-new-seen")

View File

@ -2,14 +2,12 @@ import { app } from "electron"
import { CoreV1Api } from "@kubernetes/client-node" import { CoreV1Api } from "@kubernetes/client-node"
import { LensApiRequest } from "../router" import { LensApiRequest } from "../router"
import { LensApi } from "../lens-api" import { LensApi } from "../lens-api"
import { userStore } from "../../common/user-store"
import { Cluster } from "../cluster" import { Cluster } from "../cluster"
export interface IConfigRoutePayload { export interface IConfigRoutePayload {
kubeVersion?: string; kubeVersion?: string;
clusterName?: string; clusterName?: string;
lensVersion?: string; lensVersion?: string;
lensTheme?: string;
username?: string; username?: string;
token?: string; token?: string;
allowedNamespaces?: string[]; allowedNamespaces?: string[];
@ -58,12 +56,11 @@ async function getAllowedNamespaces(cluster: Cluster) {
return namespaceList.body.items return namespaceList.body.items
.filter((ns, i) => nsAccessStatuses[i]) .filter((ns, i) => nsAccessStatuses[i])
.map(ns => ns.metadata.name) .map(ns => ns.metadata.name)
} catch(error) { } catch (error) {
const ctx = cluster.getProxyKubeconfig().getContextObject(cluster.contextName) const ctx = cluster.getProxyKubeconfig().getContextObject(cluster.contextName)
if (ctx.namespace) { if (ctx.namespace) {
return [ctx.namespace] return [ctx.namespace]
} } else {
else {
return [] return []
} }
} }
@ -94,7 +91,6 @@ class ConfigRoute extends LensApi {
const data: IConfigRoutePayload = { const data: IConfigRoutePayload = {
clusterName: cluster.contextName, clusterName: cluster.contextName,
lensVersion: app.getVersion(), lensVersion: app.getVersion(),
lensTheme: userStore.preferences.colorTheme,
kubeVersion: cluster.version, kubeVersion: cluster.version,
chartsEnabled: true, chartsEnabled: true,
isClusterAdmin: cluster.isAdmin, isClusterAdmin: cluster.isAdmin,

View File

@ -14,6 +14,7 @@ import { Checkbox } from "../checkbox";
import { Notifications } from "../notifications"; import { Notifications } from "../notifications";
import { Badge } from "../badge"; import { Badge } from "../badge";
import { Spinner } from "../spinner"; import { Spinner } from "../spinner";
import { themeStore } from "../../theme.store";
@observer @observer
export class Preferences extends React.Component { export class Preferences extends React.Component {
@ -22,20 +23,22 @@ export class Preferences extends React.Component {
@observable helmRepos: HelmRepo[] = []; @observable helmRepos: HelmRepo[] = [];
@observable helmAddedRepos = observable.map<string, HelmRepo>(); @observable helmAddedRepos = observable.map<string, HelmRepo>();
@observable themeOptions: SelectOption<string>[] = [
{ value: "kontena-dark", label: <Trans>Dark</Trans> },
{ value: "kontena-light", label: <Trans>Light</Trans> },
]
@observable downloadMirrorOptions: SelectOption<string>[] = [ @observable downloadMirrorOptions: SelectOption<string>[] = [
{ value: "default", label: "Default (Google)" }, { value: "default", label: "Default (Google)" },
{ value: "china", label: "China (Azure)" }, { value: "china", label: "China (Azure)" },
] ]
@computed get themeOptions(): SelectOption<string>[] {
return themeStore.themes.map(theme => ({
label: theme.name,
value: theme.id,
}))
}
@computed get helmOptions(): SelectOption<HelmRepo>[] { @computed get helmOptions(): SelectOption<HelmRepo>[] {
return this.helmRepos.map(repo => ({ return this.helmRepos.map(repo => ({
value: repo,
label: repo.name, label: repo.name,
value: repo,
})) }))
} }
@ -80,7 +83,6 @@ export class Preferences extends React.Component {
} }
onThemeChange = ({ value }: SelectOption<string>) => { onThemeChange = ({ value }: SelectOption<string>) => {
// themeStore.setTheme(value); // fixme: apply theme on the fly for current view
userStore.preferences.colorTheme = value; userStore.preferences.colorTheme = value;
} }
@ -129,7 +131,7 @@ export class Preferences extends React.Component {
<Select <Select
options={this.themeOptions} options={this.themeOptions}
value={preferences.colorTheme} value={preferences.colorTheme}
onChange={this.onThemeChange} onChange={({ value }: SelectOption) => preferences.colorTheme = value}
/> />
<h2><Trans>Download Mirror</Trans></h2> <h2><Trans>Download Mirror</Trans></h2>
@ -158,7 +160,7 @@ export class Preferences extends React.Component {
{this.helmLoading && <Spinner/>} {this.helmLoading && <Spinner/>}
{Array.from(this.helmAddedRepos).map(([name, repo]) => { {Array.from(this.helmAddedRepos).map(([name, repo]) => {
return ( return (
<Badge key={name} className="added-repo flex gaps align-center"> <Badge key={name} className="added-repo flex gaps align-center" title={repo.url}>
<span className="repo">{name}</span> <span className="repo">{name}</span>
<Icon <Icon
material="remove_circle_outline" material="remove_circle_outline"

View File

@ -1,5 +1,6 @@
import React, { useContext } from "react"; import React, { useContext } from "react";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { observer } from "mobx-react";
import { IPodMetrics } from "../../api/endpoints"; import { IPodMetrics } from "../../api/endpoints";
import { BarChart, cpuOptions, memoryOptions } from "../chart"; import { BarChart, cpuOptions, memoryOptions } from "../chart";
import { isMetricsEmpty, normalizeMetrics } from "../../api/endpoints/metrics.api"; import { isMetricsEmpty, normalizeMetrics } from "../../api/endpoints/metrics.api";
@ -10,7 +11,7 @@ import { themeStore } from "../../theme.store";
type IContext = IResourceMetricsValue<any, { metrics: IPodMetrics }>; type IContext = IResourceMetricsValue<any, { metrics: IPodMetrics }>;
export const ContainerCharts = () => { export const ContainerCharts = observer(() => {
const { params: { metrics }, tabId } = useContext<IContext>(ResourceMetricsContext); const { params: { metrics }, tabId } = useContext<IContext>(ResourceMetricsContext);
const { chartCapacityColor } = themeStore.activeTheme.colors; const { chartCapacityColor } = themeStore.activeTheme.colors;
@ -100,4 +101,4 @@ export const ContainerCharts = () => {
data={{ datasets: datasets[tabId] }} data={{ datasets: datasets[tabId] }}
/> />
); );
} })

View File

@ -1,7 +1,8 @@
import React, { useEffect, useRef } from "react"; import React from "react";
import merge from "lodash/merge"; import merge from "lodash/merge";
import moment from "moment"; import moment from "moment";
import Color from "color"; import Color from "color";
import { observer } from "mobx-react";
import { ChartData, ChartOptions, ChartPoint, Scriptable } from "chart.js"; import { ChartData, ChartOptions, ChartPoint, Scriptable } from "chart.js";
import { Chart, ChartKind, ChartProps } from "./chart"; import { Chart, ChartKind, ChartProps } from "./chart";
import { bytesToUnits, cssNames } from "../../utils"; import { bytesToUnits, cssNames } from "../../utils";
@ -19,139 +20,136 @@ const defaultProps: Partial<Props> = {
plugins: [ZebraStripes] plugins: [ZebraStripes]
}; };
BarChart.defaultProps = defaultProps; @observer
export class BarChart extends React.Component<Props> {
static defaultProps = defaultProps as object;
export function BarChart(props: Props) { render() {
const { name, data, className, timeLabelStep, plugins, options: customOptions, ...settings } = props; const { name, data, className, timeLabelStep, plugins, options: customOptions, ...settings } = this.props;
const { textColorPrimary, borderFaintColor, chartStripesColor } = themeStore.activeTheme.colors; const { textColorPrimary, borderFaintColor, chartStripesColor } = themeStore.activeTheme.colors;
const savedName = useRef<string>(); const getBarColor: Scriptable<string> = ({ dataset }) => {
const color = dataset.borderColor;
return Color(color).alpha(0.2).string();
}
useEffect(() => { // Remove empty sets and insert default data
savedName.current = props.name; const chartData: ChartData = {
}); ...data,
datasets: data.datasets
const getBarColor: Scriptable<string> = ({ dataset }) => { .filter(set => set.data.length)
const color = dataset.borderColor; .map(item => {
return Color(color).alpha(0.2).string();
}
// Remove empty sets and insert default data
const chartData: ChartData = {
...data,
datasets: data.datasets
.filter(set => set.data.length)
.map(item => {
return {
type: ChartKind.BAR,
borderWidth: { top: 3 },
barPercentage: 1,
categoryPercentage: 1,
...item
}
})
};
const formatTimeLabels = (timestamp: string, index: number) => {
const label = moment(parseInt(timestamp)).format("HH:mm");
const offset = " ";
if (index == 0) return offset + label;
if (index == 60) return label + offset;
return index % timeLabelStep == 0 ? label : "";
};
const barOptions: ChartOptions = {
maintainAspectRatio: false,
responsive: true,
scales: {
xAxes: [{
type: "time",
offset: true,
gridLines: {
display: false,
},
stacked: true,
ticks: {
callback: formatTimeLabels,
autoSkip: false,
source: "data",
backdropColor: "white",
fontColor: textColorPrimary,
fontSize: 11,
maxRotation: 0,
minRotation: 0
},
bounds: "data",
time: {
unit: "minute",
displayFormats: {
minute: "x"
},
parser: timestamp => moment.unix(parseInt(timestamp))
}
}],
yAxes: [{
position: "right",
gridLines: {
color: borderFaintColor,
drawBorder: false,
tickMarkLength: 0,
zeroLineWidth: 0
},
ticks: {
maxTicksLimit: 6,
fontColor: textColorPrimary,
fontSize: 11,
padding: 8,
min: 0
}
}]
},
tooltips: {
mode: "index",
position: "cursor",
callbacks: {
title: tooltipItems => {
const now = new Date().getTime()
if (new Date(tooltipItems[0].xLabel).getTime() > now) return "";
return `${tooltipItems[0].xLabel}`
},
labelColor: ({ datasetIndex }) => {
return { return {
borderColor: "darkgray", type: ChartKind.BAR,
backgroundColor: chartData.datasets[datasetIndex].borderColor as string borderWidth: { top: 3 },
barPercentage: 1,
categoryPercentage: 1,
...item
}
})
};
const formatTimeLabels = (timestamp: string, index: number) => {
const label = moment(parseInt(timestamp)).format("HH:mm");
const offset = " ";
if (index == 0) return offset + label;
if (index == 60) return label + offset;
return index % timeLabelStep == 0 ? label : "";
};
const barOptions: ChartOptions = {
maintainAspectRatio: false,
responsive: true,
scales: {
xAxes: [{
type: "time",
offset: true,
gridLines: {
display: false,
},
stacked: true,
ticks: {
callback: formatTimeLabels,
autoSkip: false,
source: "data",
backdropColor: "white",
fontColor: textColorPrimary,
fontSize: 11,
maxRotation: 0,
minRotation: 0
},
bounds: "data",
time: {
unit: "minute",
displayFormats: {
minute: "x"
},
parser: timestamp => moment.unix(parseInt(timestamp))
}
}],
yAxes: [{
position: "right",
gridLines: {
color: borderFaintColor,
drawBorder: false,
tickMarkLength: 0,
zeroLineWidth: 0
},
ticks: {
maxTicksLimit: 6,
fontColor: textColorPrimary,
fontSize: 11,
padding: 8,
min: 0
}
}]
},
tooltips: {
mode: "index",
position: "cursor",
callbacks: {
title: tooltipItems => {
const now = new Date().getTime()
if (new Date(tooltipItems[0].xLabel).getTime() > now) return "";
return `${tooltipItems[0].xLabel}`
},
labelColor: ({ datasetIndex }) => {
return {
borderColor: "darkgray",
backgroundColor: chartData.datasets[datasetIndex].borderColor as string
}
} }
} }
},
animation: {
duration: 0
},
elements: {
rectangle: {
backgroundColor: getBarColor.bind(null)
}
},
plugins: {
ZebraStripes: {
stripeColor: chartStripesColor
}
} }
}, };
animation: { const options = merge(barOptions, customOptions);
duration: 0 if (chartData.datasets.length == 0) {
}, return <NoMetrics/>
elements: {
rectangle: {
backgroundColor: getBarColor.bind(null)
}
},
plugins: {
ZebraStripes: {
stripeColor: chartStripesColor
}
} }
}; return (
const options = merge(barOptions, customOptions); <Chart
if (chartData.datasets.length == 0) { className={cssNames("BarChart flex box grow column", className)}
return <NoMetrics/> type={ChartKind.BAR}
data={chartData}
options={options}
plugins={plugins}
{...settings}
/>
)
} }
return (
<Chart
className={cssNames("BarChart flex box grow column", className)}
type={ChartKind.BAR}
data={chartData}
options={options}
plugins={plugins}
{...settings}
/>
)
} }
// Default options for all charts containing memory units (network, disk, memory, etc) // Default options for all charts containing memory units (network, disk, memory, etc)

View File

@ -1,5 +1,6 @@
import "./pie-chart.scss"; import "./pie-chart.scss";
import React from "react"; import React from "react";
import { observer } from "mobx-react";
import ChartJS, { ChartOptions } from "chart.js"; import ChartJS, { ChartOptions } from "chart.js";
import { Chart, ChartProps } from "./chart"; import { Chart, ChartProps } from "./chart";
import { cssNames } from "../../utils"; import { cssNames } from "../../utils";
@ -8,6 +9,7 @@ import { themeStore } from "../../theme.store";
interface Props extends ChartProps { interface Props extends ChartProps {
} }
@observer
export class PieChart extends React.Component<Props> { export class PieChart extends React.Component<Props> {
render() { render() {
const { data, className, options, ...chartProps } = this.props const { data, className, options, ...chartProps } = this.props

View File

@ -6,6 +6,7 @@ import { BottomBar } from "./bottom-bar";
import { cssNames, IClassName } from "../../utils"; import { cssNames, IClassName } from "../../utils";
import { Terminal } from "../dock/terminal"; import { Terminal } from "../dock/terminal";
import { i18nStore } from "../../i18n"; import { i18nStore } from "../../i18n";
import { themeStore } from "../../theme.store";
interface Props { interface Props {
className?: IClassName; className?: IClassName;
@ -14,8 +15,11 @@ interface Props {
export class ClusterManager extends React.Component<Props> { export class ClusterManager extends React.Component<Props> {
static async init() { static async init() {
await i18nStore.init() await Promise.all([
await Terminal.preloadFonts() i18nStore.init(),
themeStore.init(),
Terminal.preloadFonts(),
])
} }
render() { render() {

View File

@ -1,5 +1,5 @@
import debounce from "lodash/debounce"; import debounce from "lodash/debounce";
import { autorun } from "mobx"; import { reaction, toJS } from "mobx";
import { Terminal as XTerm } from "xterm"; import { Terminal as XTerm } from "xterm";
import { FitAddon } from "xterm-addon-fit"; import { FitAddon } from "xterm-addon-fit";
import { dockStore, TabId } from "./dock.store"; import { dockStore, TabId } from "./dock.store";
@ -20,7 +20,7 @@ export class Terminal {
Terminal.spawningPool = pool; Terminal.spawningPool = pool;
} }
static async preloadFonts(){ static async preloadFonts() {
const fontPath = require("../fonts/roboto-mono-nerd.ttf").default; // eslint-disable-line @typescript-eslint/no-var-requires const fontPath = require("../fonts/roboto-mono-nerd.ttf").default; // eslint-disable-line @typescript-eslint/no-var-requires
const fontFace = new FontFace("RobotoMono", `url(${fontPath})`); const fontFace = new FontFace("RobotoMono", `url(${fontPath})`);
await fontFace.load(); await fontFace.load();
@ -33,7 +33,7 @@ export class Terminal {
public disposers: Function[] = []; public disposers: Function[] = [];
@autobind() @autobind()
protected setTheme(colors = themeStore.activeTheme.colors) { protected setTheme(colors: Record<string, string>) {
// Replacing keys stored in styles to format accepted by terminal // Replacing keys stored in styles to format accepted by terminal
// E.g. terminalBrightBlack -> brightBlack // E.g. terminalBrightBlack -> brightBlack
const colorPrefix = "terminal" const colorPrefix = "terminal"
@ -94,19 +94,18 @@ export class Terminal {
this.xterm.attachCustomKeyEventHandler(this.keyHandler); this.xterm.attachCustomKeyEventHandler(this.keyHandler);
// bind events // bind events
const onResizeDisposer = dockStore.onResize(this.onResize); const onDataHandler = this.xterm.onData(this.onData);
const onData = this.xterm.onData(this.onData);
const onThemeChangeDisposer = autorun(() => this.setTheme(themeStore.activeTheme.colors));
this.viewport.addEventListener("scroll", this.onScroll); this.viewport.addEventListener("scroll", this.onScroll);
this.api.onReady.addListener(this.onClear, { once: true }); // clear status logs (connecting..) this.api.onReady.addListener(this.onClear, { once: true }); // clear status logs (connecting..)
this.api.onData.addListener(this.onApiData); this.api.onData.addListener(this.onApiData);
window.addEventListener("resize", this.onResize); window.addEventListener("resize", this.onResize);
// add clean-up handlers to be called on destroy
this.disposers.push( this.disposers.push(
onResizeDisposer, reaction(() => toJS(themeStore.activeTheme.colors), this.setTheme, {
onThemeChangeDisposer, fireImmediately: true
() => onData.dispose(), }),
dockStore.onResize(this.onResize),
() => onDataHandler.dispose(),
() => this.fitAddon.dispose(), () => this.fitAddon.dispose(),
() => this.api.removeAllListeners(), () => this.api.removeAllListeners(),
() => window.removeEventListener("resize", this.onResize), () => window.removeEventListener("resize", this.onResize),
@ -171,7 +170,7 @@ export class Terminal {
// Handle custom hotkey bindings // Handle custom hotkey bindings
if (ctrlKey) { if (ctrlKey) {
switch (code) { switch (code) {
// Ctrl+C: prevent terminal exit on windows / linux (?) // Ctrl+C: prevent terminal exit on windows / linux (?)
case "KeyC": case "KeyC":
if (this.xterm.hasSelection()) return false; if (this.xterm.hasSelection()) return false;
break; break;

View File

@ -8,7 +8,7 @@
grid-template-columns: 1fr 40%; grid-template-columns: 1fr 40%;
> * { > * {
@include hidden-scrollbar; @include custom-scrollbar;
--flex-gap: #{$spacing}; --flex-gap: #{$spacing};
padding: $spacing; padding: $spacing;
} }

View File

@ -1,91 +1,98 @@
import { action, autorun, computed, observable, reaction } from "mobx"; import { computed, observable, reaction } from "mobx";
import { autobind, createStorage } from "./utils"; import { autobind } from "./utils";
import { Notifications } from "./components/notifications"; import { userStore } from "../common/user-store";
import { Theme, ThemeType } from "../common/user-store"; import logger from "../main/logger";
export type ThemeId = string;
export enum ThemeType {
DARK = "dark",
LIGHT = "light",
}
export interface Theme {
id: ThemeId; // filename without .json-extension
type: ThemeType;
name?: string;
colors?: Record<string, string>;
description?: string;
author?: string;
}
@autobind() @autobind()
export class ThemeStore { export class ThemeStore {
protected style = document.createElement("style"); protected styles: HTMLStyleElement;
readonly defaultTheme: Theme = { // bundled themes from `themes/${themeId}.json`
name: "kontena-dark", @observable themes: Theme[] = [
type: ThemeType.DARK, { id: "kontena-dark", type: ThemeType.DARK },
colors: {}, { id: "kontena-light", type: ThemeType.LIGHT },
}; ];
@observable activeThemeId = this.defaultTheme.name; // theme's filename without extension @computed get activeThemeId() {
@observable themes = observable.map<string, Theme>([], { deep: false }); return userStore.preferences.colorTheme;
}
@computed get activeTheme() { @computed get activeTheme(): Theme {
return this.themes.get(this.activeThemeId) || this.defaultTheme; const activeTheme = this.themes.find(theme => theme.id === this.activeThemeId) || this.themes[0];
return {
colors: {},
...activeTheme,
}
} }
constructor() { constructor() {
const storage = createStorage("theme", this.activeThemeId); // auto-apply active theme
this.activeThemeId = storage.get(); reaction(() => this.activeThemeId, async themeId => {
try {
// init await this.loadTheme(themeId);
this.style.id = "lens-theme" this.applyTheme();
document.head.prepend(this.style); } catch (err) {
this.setTheme(this.activeThemeId); userStore.resetTheme();
}
// save active theme-id in local storage }, {
reaction(() => this.activeThemeId, themeId => storage.set(themeId), {
fireImmediately: true
});
// auto-apply colors to dom from active theme
reaction(() => this.activeTheme, this.onChange, {
fireImmediately: true, fireImmediately: true,
delay: 150,
});
// apply theme from configuration
import("./config.store").then(({ configStore }) => {
autorun(() => {
const themeId = configStore.config.lensTheme;
if (themeId && themeId !== this.activeThemeId) {
this.setTheme(themeId);
}
});
}) })
} }
protected onChange = (theme: Theme) => { async init() {
let cssText = "\n" // preload all themes
Object.entries(theme.colors).forEach(([propName, color]) => { await Promise.all(
cssText += `--${propName}: ${color} !important;\n` this.themes.map(theme => this.loadTheme(theme.id))
}); );
this.style.textContent = `:root {${cssText}} `;
} }
async load(themeId: string, { showErrorNotification = true } = {}): Promise<Theme> { getThemeById(themeId: ThemeId): Theme {
if (this.themes.has(themeId)) { return this.themes.find(theme => theme.id === themeId)
return this.themes.get(themeId); }
}
protected async loadTheme(themeId: ThemeId): Promise<Theme> {
try { try {
const theme: Theme = require( // eslint-disable-line @typescript-eslint/no-var-requires // todo: figure out why await import() doesn't work
/* webpackMode: "lazy", webpackChunkName: "theme/[request]" */ const theme = require( // eslint-disable-line @typescript-eslint/no-var-requires
/* webpackChunkName: "themes/[name]" */
`./themes/${themeId}.json` `./themes/${themeId}.json`
); );
this.themes.set(themeId, theme); const existingTheme = this.getThemeById(themeId);
return theme; if (existingTheme) {
Object.assign(existingTheme, theme); // merge
}
return existingTheme;
} catch (err) { } catch (err) {
if (showErrorNotification) Notifications.error(err.toString()); logger.error(`Can't load theme "${themeId}": ${err}`);
throw err;
} }
} }
@action protected applyTheme(theme = this.activeTheme) {
async setTheme(themeId = this.defaultTheme.name) { if (!this.styles) {
try { this.styles = document.createElement("style");
await this.load(themeId); this.styles.id = "lens-theme"
this.activeThemeId = themeId; document.head.prepend(this.styles);
} catch (err) {
if (themeId !== this.defaultTheme.name) {
this.setTheme(); // fallback to default theme
}
} }
const cssVars = Object.entries(theme.colors).map(([cssName, color]) => {
return `--${cssName}: ${color} !important;`
});
this.styles.textContent = `:root {\n${cssVars.join("\n")}}`;
} }
} }

View File

@ -1,6 +1,7 @@
{ {
"name": "Lens Dark Theme", "name": "Dark (Lens)",
"type": "dark", "type": "dark",
"description": "Original Lens dark theme",
"author": "Lakend Labs", "author": "Lakend Labs",
"colors": { "colors": {
"blue": "#3d90ce", "blue": "#3d90ce",

View File

@ -1,6 +1,7 @@
{ {
"name": "Lens Light Theme", "name": "Light (Lens)",
"type": "light", "type": "light",
"description": "Original Lens light theme",
"author": "Lakend Labs", "author": "Lakend Labs",
"colors": { "colors": {
"blue": "#3d90ce", "blue": "#3d90ce",