Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions code/src/cljs/sixsq/nuvla/ui/app/view.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns sixsq.nuvla.ui.app.view
(:require [re-frame.core :refer [dispatch subscribe]]
[sixsq.nuvla.ui.common-components.i18n.subs :as i18n-subs]
[sixsq.nuvla.ui.common-components.i18n.views :as i18n-views]
[sixsq.nuvla.ui.common-components.intercom.views :as intercom]
[sixsq.nuvla.ui.main.components :as main-components]
[sixsq.nuvla.ui.main.subs :as subs]
Expand Down Expand Up @@ -36,8 +37,8 @@
[:<>
(let [session @(subscribe [::session-subs/session])]
(if session
[FollowRedirect]
[WatcherRedirectProtectedPage]))])
[FollowRedirect]
[WatcherRedirectProtectedPage]))])

(defn RouterView []
(let [CurrentView @(subscribe [::route-subs/current-view])
Expand Down Expand Up @@ -77,6 +78,23 @@
[main-views/SubscriptionRequiredModal]
[main-views/Footer]]]]])

(defn LayoutCallback []
[:div {:class "login-left"}
[:div {:style {:background-color "#C10E12"}}
[:div {:style {:position :absolute
:right 10
:padding 10}} [i18n-views/LocaleDropdown]]
[ui/Image {:alt "logo"
:src "/ui/images/nuvla-logo.png"
:size "small"
:centered true}]]
[:div {:style {:margin-top "10%"
:padding "1em"
:background-color "rgba(0,0,0,0.5)"
:box-shadow "0px 0px 50px black"
}}
[RouterView]]])

(defn Loader []
(let [tr (subscribe [::i18n-subs/tr])
error? (subscribe [::api-subs/cloud-entry-point-error?])]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

(def dictionary
{:en {
:please-click-to-proceed "Please click here to proceed"
:group-name-validation-error "Group name should start with an alphanumeric character. Space, dash and underscore characters are allowed but not at the end of the group name."
:group-descr-validation-error "Description should not be an empty string."
:stop-deployment-remove-volumes "Remove volumes"
:stop-deployment-remove-images "Remove images"
:stop-deployment-remove-opts-require-ne-2.19 "The selected options require NuvlaEdge version 2.19 or higher to be taken into account."
Expand Down Expand Up @@ -1207,6 +1210,9 @@
}

:fr {
:please-click-to-proceed "Veuillez cliquer ici pour continuer"
:group-name-validation-error "Le nom du groupe doit commencer par un caractère alphanumérique. Les espaces, les tirets et les traits de soulignement sont autorisés, mais pas à la fin du nom de groupe."
:group-descr-validation-error "La description ne doit pas être une chaîne de caractères vide."
:stop-deployment-remove-volumes "Supprimer les volumes"
:stop-deployment-remove-images "Supprimer les images"
:stop-deployment-remove-opts-require-ne-2.19 "Les options sélectionnées nécessitent la version 2.19 ou supérieure de NuvlaEdge pour être prises en compte."
Expand Down
2 changes: 2 additions & 0 deletions code/src/cljs/sixsq/nuvla/ui/db/spec.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
[sixsq.nuvla.ui.pages.edges-detail.spec :as edges-detail]
[sixsq.nuvla.ui.pages.edges.spec :as edges]
[sixsq.nuvla.ui.pages.profile.spec :as profile]
[sixsq.nuvla.ui.pages.groups.spec :as groups]
[sixsq.nuvla.ui.routing.router :refer [router]]
[sixsq.nuvla.ui.session.spec :as session]))

Expand Down Expand Up @@ -69,4 +70,5 @@
resource-log/defaults
deployment-sets/defaults
deployment-sets-detail/defaults
groups/defaults
{:router router}))
6 changes: 5 additions & 1 deletion code/src/cljs/sixsq/nuvla/ui/main/spec.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,13 @@
:label-kw :infra-service-short
:icon icons/i-cloud
:order 80}
"groups" {:key routes/groups
:label-kw :groups
:icon icons/i-users
:order 90}
"api" {:key routes/api
:label-kw :api
:icon icons/i-code
:order 90}}
:order 100}}
::open-modal nil
::stripe nil})
20 changes: 20 additions & 0 deletions code/src/cljs/sixsq/nuvla/ui/pages/callback/views.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
(ns sixsq.nuvla.ui.pages.callback.views
(:require [clojure.string :as str]
[re-frame.core :refer [dispatch subscribe]]
[sixsq.nuvla.ui.common-components.i18n.subs :as i18n-subs]
[sixsq.nuvla.ui.main.components :as main-components]
[sixsq.nuvla.ui.main.subs :as main-subs]
[sixsq.nuvla.ui.utils.semantic-ui :as ui]
[sixsq.nuvla.ui.routing.subs :as route-subs]
[sixsq.nuvla.ui.utils.semantic-ui-extensions :as uix]))

(defn CallbackView
[{{:keys [callback-url]} :query-params :as f}]
(let [tr @(subscribe [::i18n-subs/tr])]
[:div {:style {:display :flex
:justify-content :center}}
[ui/Button {:size "large"
:primary true
:href callback-url
:data-reitit-handle-click "false"}
[:b (tr [:please-click-to-proceed])]]]))
98 changes: 98 additions & 0 deletions code/src/cljs/sixsq/nuvla/ui/pages/groups/events.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
(ns sixsq.nuvla.ui.pages.groups.events
(:require [day8.re-frame.http-fx]
[re-frame.core :refer [dispatch reg-event-db reg-event-fx]]
[sixsq.nuvla.ui.cimi-api.effects :as cimi-api-fx]
[sixsq.nuvla.ui.common-components.messages.events :as messages-events]
[sixsq.nuvla.ui.config :as config]
[sixsq.nuvla.ui.session.events :as session-events]
[sixsq.nuvla.ui.session.spec :as session-spec]
[sixsq.nuvla.ui.pages.groups.spec :as spec]
[sixsq.nuvla.ui.utils.response :as response]))

(reg-event-fx
::add-group
(fn [{_db :db} [_ {:keys [parent-group group-identifier group-name group-desc loading?]}]]
(let [on-success #(let [{:keys [status message resource-id]} (response/parse %)]
(dispatch [::session-events/search-groups])
(dispatch [::messages-events/add
{:header (cond-> (str "added " resource-id)
status (str " (" status ")"))
:content message
:type :success}])
(reset! loading? false))]
(if parent-group
{::cimi-api-fx/operation
[(:id parent-group) "add-subgroup"
on-success
:data {:group-identifier group-identifier
:name group-name
:description group-desc}]}
{::cimi-api-fx/add
["group" {:template {:href "group-template/generic"
:group-identifier group-identifier}
:name group-name
:description group-desc} on-success]}))))

(reg-event-fx
::edit-group
(fn [_ [_ group]]
(let [id (:id group)]
{::cimi-api-fx/edit [id group #(if (instance? js/Error %)
(let [{:keys [status message]} (response/parse-ex-info %)]
(dispatch [::messages-events/add
{:header (cond-> "Group update failed"
status (str " (" status ")"))
:content message
:type :error}]))
(do
(dispatch [::session-events/search-groups])
(dispatch [::messages-events/add
{:header "Group updated"
:content "Group updated successfully."
:type :info}])))]})))

(reg-event-fx
::invite-to-group
(fn [{db :db} [_ group-id username]]
(let [on-error #(let [{:keys [status message]} (response/parse-ex-info %)]
(dispatch [::messages-events/add
{:header (cond-> (str "Invitation to " group-id " for " username " failed!")
status (str " (" status ")"))
:content message
:type :error}]))
on-success #(do (dispatch [::messages-events/add
{:header "Invitation successfully sent to user"
:content (str "User will appear in " group-id
" when he accept the invitation sent to his email address.")
:type :info}])
(dispatch [::get-pending-invitations group-id]))
data {:username username
:redirect-url (str (::session-spec/server-redirect-uri db)
"?message=join-group-accepted")
:set-password-url (str @config/path-prefix "/set-password")}]
{::cimi-api-fx/operation [group-id "invite" on-success :on-error on-error :data data]})))

(reg-event-fx
::get-pending-invitations
(fn [{db :db} [_ group-id]]
(let [on-success #(dispatch [::set-pending-invitations %])]
{:db (assoc db ::spec/pending-invitations nil)
::cimi-api-fx/operation
[group-id "get-pending-invitations" on-success :on-error #()]})))

(reg-event-db
::set-pending-invitations
(fn [db [_ pending-invitations]]
(assoc db ::spec/pending-invitations pending-invitations)))

(reg-event-fx
::revoke
(fn [_ [_ {group-id :id :as _group} invited-email]]
(let [on-success #(do (dispatch [::messages-events/add
{:header "Invitation successfully revoked"
:content (str "Invitation successfully revoked for "
invited-email " from " group-id ".")
:type :info}])
(dispatch [::get-pending-invitations group-id]))]
{::cimi-api-fx/operation [group-id "revoke-invitation" on-success
:data {:email invited-email}]})))
4 changes: 4 additions & 0 deletions code/src/cljs/sixsq/nuvla/ui/pages/groups/spec.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(ns sixsq.nuvla.ui.pages.groups.spec
(:require [clojure.spec.alpha :as s]))

(def defaults {::pending-invitations nil})
64 changes: 64 additions & 0 deletions code/src/cljs/sixsq/nuvla/ui/pages/groups/subs.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
(ns sixsq.nuvla.ui.pages.groups.subs
(:require [clojure.string :as str]
[re-frame.core :refer [reg-sub]]
[sixsq.nuvla.ui.pages.groups.spec :as spec]
[sixsq.nuvla.ui.session.subs :as session-subs]
[sixsq.nuvla.ui.utils.general :as general-utils]))

(reg-sub
::pending-invitations
:-> ::spec/pending-invitations)

(reg-sub
::indexed-groups
:<- [::session-subs/groups]
:<- [::session-subs/peers]
(fn [[groups peers]]
(map (fn [{:keys [id name users] :as _group}]
{:id id
:keywords (remove nil?
(concat
[id name]
users
(map #(get peers %) users)))})
groups)))


(defn matching-group
[pattern {:keys [keywords]}]
(some #(re-matches pattern %) keywords))

(defn filter-groups
[allowed-ids group]
(let [children (:children group)
filtered-children (when children
(->> children
(map #(filter-groups allowed-ids %))
(remove nil?)))]
;; keep this group if its id is allowed OR it has any kept children
(when (or (allowed-ids (:id group))
(seq filtered-children))
(cond-> (assoc group :children filtered-children)
(empty? filtered-children) (dissoc :children)))))

(defn filter-groups-tree
[allowed-ids groups]
(->> groups
(map #(filter-groups allowed-ids %))
(remove nil?)))


(reg-sub
::filter-groups-hierarchy
:<- [::indexed-groups]
:<- [::session-subs/groups-hierarchies]
(fn [[indexed-groups groups-hierarchies] [_ search]]
(let [groups-hierarchies (filter (fn [root-group] (not (#{"group/nuvla-user" "group/nuvla-nuvlabox" "group/nuvla-anon" "group/nuvla-vpn"} (:id root-group)))) groups-hierarchies)]
(if (str/blank? search)
groups-hierarchies
(let [pattern (re-pattern (str "(?i).*" (general-utils/regex-escape search) ".*"))
allowed-ids (->> indexed-groups
(keep #(when (matching-group pattern %) (:id %)))
set)]
(filter-groups-tree allowed-ids groups-hierarchies))
))))
Loading
Loading