mirror of
https://github.com/penpot/penpot.git
synced 2026-05-19 14:14:05 -04:00
🎉 Show dedicated screen when Nitrate is unavailable
This commit is contained in:
@@ -144,6 +144,14 @@
|
||||
{::yres/status 404
|
||||
::yres/body (ex-data err)})
|
||||
|
||||
(defmethod handle-error :nitrate-unavailable
|
||||
[err request _]
|
||||
(binding [l/*context* (request->context request)]
|
||||
(l/warn :hint "nitrate is unreachable; blocking request" :cause err)
|
||||
{::yres/status 503
|
||||
::yres/body (-> (ex-data err)
|
||||
(assoc :type :nitrate-unavailable))}))
|
||||
|
||||
(defmethod handle-error :internal
|
||||
[error request parent-cause]
|
||||
(binding [l/*context* (request->context request)]
|
||||
|
||||
@@ -61,13 +61,26 @@
|
||||
(let [response (handler)
|
||||
status (:status response)]
|
||||
(when-not status
|
||||
(l/error :hint "could't do the nitrate request, it is probably down"
|
||||
(l/error :hint "couldn't do the nitrate request, it is probably down"
|
||||
:uri uri)
|
||||
;; TODO decide what to do when Nitrate is inaccesible
|
||||
nil)
|
||||
(ex/raise :type :nitrate-unavailable
|
||||
:hint (str "nitrate is unreachable at " uri)))
|
||||
(cond
|
||||
(>= status 500)
|
||||
;; Nitrate is up enough to answer (or the proxy is) but the
|
||||
;; service itself is failing; treat as unavailable so callers
|
||||
;; surface the static error page.
|
||||
(do
|
||||
(l/error :hint "nitrate request failed with server error status"
|
||||
:uri uri
|
||||
:status status
|
||||
:body (:body response))
|
||||
(ex/raise :type :nitrate-unavailable
|
||||
:status status
|
||||
:hint (str "nitrate is unavailable, HTTP " status " at " uri)))
|
||||
|
||||
(>= status 400)
|
||||
;; For error status codes (4xx, 5xx), fail immediately without validation
|
||||
;; For client error status codes (4xx), fail immediately without validation
|
||||
(do
|
||||
(when (not= status 404) ;; Don't need to log 404
|
||||
(l/error :hint "nitrate request failed with error status"
|
||||
@@ -434,21 +447,27 @@
|
||||
(defn add-nitrate-licence-to-profile
|
||||
"Enriches a profile map with subscription information from Nitrate.
|
||||
Adds a :subscription field containing the user's license details.
|
||||
Returns the original profile unchanged if the request fails."
|
||||
Returns the original profile unchanged if the request fails for a reason
|
||||
other than Nitrate being unreachable. When Nitrate is unreachable the
|
||||
`:nitrate-unavailable` exception propagates so the request is rejected."
|
||||
[cfg profile]
|
||||
(try
|
||||
(let [subscription (call cfg :get-subscription {:profile-id (:id profile)})]
|
||||
(assoc profile :subscription subscription))
|
||||
(catch Throwable cause
|
||||
(l/error :hint "failed to get nitrate licence"
|
||||
:profile-id (:id profile)
|
||||
:cause cause)
|
||||
profile)))
|
||||
(if (= :nitrate-unavailable (-> cause ex-data :type))
|
||||
(throw cause)
|
||||
(do
|
||||
(l/error :hint "failed to get nitrate licence"
|
||||
:profile-id (:id profile)
|
||||
:cause cause)
|
||||
profile)))))
|
||||
|
||||
(defn add-org-info-to-team
|
||||
"Enriches a team map with organization information from Nitrate.
|
||||
Adds organization-id, organization-name, organization-slug, organization-owner-id, and your-penpot fields.
|
||||
Returns the original team unchanged if the request fails or org data is nil."
|
||||
Returns the original team unchanged if the request fails or org data is nil.
|
||||
Propagates `:nitrate-unavailable` so the request is rejected when Nitrate is unreachable."
|
||||
[cfg team params]
|
||||
(try
|
||||
(let [params (assoc (or params {}) :team-id (:id team))
|
||||
@@ -461,10 +480,13 @@
|
||||
(assoc :is-default (or (:is-default team) (true? (:is-your-penpot team-with-org)))))
|
||||
team))
|
||||
(catch Throwable cause
|
||||
(l/error :hint "failed to get team organization info"
|
||||
:team-id (:id team)
|
||||
:cause cause)
|
||||
team)))
|
||||
(if (= :nitrate-unavailable (-> cause ex-data :type))
|
||||
(throw cause)
|
||||
(do
|
||||
(l/error :hint "failed to get team organization info"
|
||||
:team-id (:id team)
|
||||
:cause cause)
|
||||
team)))))
|
||||
|
||||
(defn set-team-organization
|
||||
"Associates a team with an organization in Nitrate.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1466.16 8469.63 101.36 30.92" fill="currentColor">
|
||||
<path d="M-1448.93359375,8500.544921875L-1466.1591796875,8493.12890625L-1454.9228515625,8478.05078125L-1430.9052734375,8471.634765625L-1424.8349609375,8494.107421875L-1448.93359375,8500.544921875M-1457.3271484375,8492.91015625L-1450.6474609375,8495.79296875L-1454.0634765625,8483.091796875L-1458.3544921875,8488.85546875L-1457.3271484375,8492.91015625M-1451.5966796875,8481.1484375L-1449.9765625,8487.171875L-1428.296875,8481.37890625L-1429.890625,8475.349609375L-1451.5966796875,8481.1484375M-1449.1455078125,8490.2626953125L-1447.5341796875,8496.25390625L-1425.826171875,8490.455078125L-1427.44921875,8484.466796875L-1449.1455078125,8490.2626953125"/>
|
||||
<path d="M-1366.314453125,8469.626953125L-1412.9775390625,8469.626953125L-1413.001953125,8492.8994140625L-1366.2548828125,8492.8984375C-1366.2548828125,8492.8984375,-1364.8046875,8489.115234375,-1364.82421875,8481.5634765625C-1364.8447265625,8473.6005859375,-1366.314453125,8469.626953125,-1366.314453125,8469.626953125M-1370.208984375,8473.4765625L-1370.208984375,8479.7119140625L-1412.96484375,8479.7119140625L-1412.9921875,8473.4765625L-1370.208984375,8473.4765625M-1370.208984375,8482.912109375L-1370.208984375,8489.115234375L-1412.9931640625,8489.115234375L-1412.9814453125,8482.912109375L-1370.208984375,8482.912109375"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -354,6 +354,7 @@
|
||||
(derive :not-found ::exceptional-state)
|
||||
(derive :bad-gateway ::exceptional-state)
|
||||
(derive :service-unavailable ::exceptional-state)
|
||||
(derive :nitrate-unavailable ::exceptional-state)
|
||||
|
||||
(defmethod ptk/handle-error ::exceptional-state
|
||||
[error]
|
||||
|
||||
@@ -86,6 +86,10 @@
|
||||
(= 502 status)
|
||||
(rx/throw (ex-info "http error" {:type :bad-gateway}))
|
||||
|
||||
(and (= 503 status)
|
||||
(= :nitrate-unavailable (:type body)))
|
||||
(rx/throw (ex-info "http error" {:type :nitrate-unavailable}))
|
||||
|
||||
(= 503 status)
|
||||
(rx/throw (ex-info "http error" {:type :service-unavailable}))
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
(def ^:svg-id brand-google "brand-google")
|
||||
(def ^:svg-id loader "loader")
|
||||
(def ^:svg-id logo-error-screen "logo-error-screen")
|
||||
(def ^:svg-id logo-nitrate-unavailable "logo-nitrate-unavailable")
|
||||
(def ^:svg-id logo-subscription "logo-subscription")
|
||||
(def ^:svg-id logo-subscription-light "logo-subscription-light")
|
||||
(def ^:svg-id nitrate-welcome "nitrate-welcome")
|
||||
|
||||
@@ -320,6 +320,16 @@
|
||||
[:div {:class (stl/css :sign-info)}
|
||||
[:button {:on-click on-click} (tr "labels.retry")]]]))
|
||||
|
||||
(mf/defc nitrate-unavailable*
|
||||
[]
|
||||
[:section {:class (stl/css :nitrate-unavailable-layout)}
|
||||
[:div {:class (stl/css :nitrate-unavailable-content)}
|
||||
[:> raw-svg* {:id "logo-nitrate-unavailable" :class (stl/css :nitrate-unavailable-logo)}]
|
||||
[:p {:class (stl/css :nitrate-unavailable-message)}
|
||||
(tr "labels.nitrate-unavailable.main-message")]]
|
||||
[:p {:class (stl/css :nitrate-unavailable-footer)}
|
||||
(tr "labels.copyright-period")]])
|
||||
|
||||
(mf/defc webgl-context-lost*
|
||||
[]
|
||||
(let [on-reload (mf/use-fn #(js/location.reload))]
|
||||
@@ -491,6 +501,9 @@
|
||||
:service-unavailable
|
||||
[:> service-unavailable*]
|
||||
|
||||
:nitrate-unavailable
|
||||
[:> nitrate-unavailable*]
|
||||
|
||||
[:> internal-error* props])))
|
||||
|
||||
(mf/defc context-wrapper*
|
||||
|
||||
@@ -13,6 +13,51 @@
|
||||
background-color: var(--color-background-secondary);
|
||||
}
|
||||
|
||||
.nitrate-unavailable-layout {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: var(--color-background-primary);
|
||||
padding: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.nitrate-unavailable-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.nitrate-unavailable-logo {
|
||||
inline-size: 146px;
|
||||
block-size: 64px;
|
||||
color: var(--color-foreground-primary);
|
||||
transform: scale(1,-1);
|
||||
}
|
||||
|
||||
.nitrate-unavailable-message {
|
||||
@include t.use-typography("title-large");
|
||||
|
||||
margin: 0;
|
||||
max-inline-size: 32rem;
|
||||
text-align: center;
|
||||
color: var(--color-foreground-primary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nitrate-unavailable-footer {
|
||||
@include t.use-typography("title-medium");
|
||||
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
||||
|
||||
.deco-before,
|
||||
.deco-after {
|
||||
position: absolute;
|
||||
|
||||
@@ -2906,6 +2906,12 @@ msgstr "New password"
|
||||
msgid "labels.next"
|
||||
msgstr "Next"
|
||||
|
||||
#: src/app/main/ui/static.cljs:325
|
||||
msgid "labels.nitrate-unavailable.main-message"
|
||||
msgstr ""
|
||||
"Penpot is temporarily unavailable due to a system issue. Please try again "
|
||||
"shortly."
|
||||
|
||||
#: src/app/main/ui/dashboard/comments.cljs:122, src/app/main/ui/workspace/comments.cljs:162
|
||||
msgid "labels.no-comments-available"
|
||||
msgstr "You're all caught up! New comment notifications will appear here."
|
||||
|
||||
@@ -2815,6 +2815,12 @@ msgstr "Nueva contraseña"
|
||||
msgid "labels.next"
|
||||
msgstr "Siguiente"
|
||||
|
||||
#: src/app/main/ui/static.cljs:325
|
||||
msgid "labels.nitrate-unavailable.main-message"
|
||||
msgstr ""
|
||||
"Penpot no está disponible temporalmente debido a un problema del sistema. "
|
||||
"Por favor, inténtalo de nuevo en unos momentos."
|
||||
|
||||
#: src/app/main/ui/dashboard/comments.cljs:122, src/app/main/ui/workspace/comments.cljs:162
|
||||
msgid "labels.no-comments-available"
|
||||
msgstr "¡Ya estás al día! Nuevas notificaciones de comentarios aparecerán aquí."
|
||||
|
||||
Reference in New Issue
Block a user