diff --git a/api/http/handler/handler.go b/api/http/handler/handler.go
index 9dc541641..7bb72dbb9 100644
--- a/api/http/handler/handler.go
+++ b/api/http/handler/handler.go
@@ -4,6 +4,8 @@ import (
"net/http"
"strings"
+ "github.com/portainer/portainer/api/http/handler/support"
+
"github.com/portainer/portainer/api/http/handler/schedules"
"github.com/portainer/portainer/api/http/handler/roles"
@@ -48,6 +50,7 @@ type Handler struct {
SettingsHandler *settings.Handler
StackHandler *stacks.Handler
StatusHandler *status.Handler
+ SupportHandler *support.Handler
TagHandler *tags.Handler
TeamMembershipHandler *teammemberships.Handler
TeamHandler *teams.Handler
@@ -96,6 +99,8 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
http.StripPrefix("/api", h.StackHandler).ServeHTTP(w, r)
case strings.HasPrefix(r.URL.Path, "/api/status"):
http.StripPrefix("/api", h.StatusHandler).ServeHTTP(w, r)
+ case strings.HasPrefix(r.URL.Path, "/api/support"):
+ http.StripPrefix("/api", h.SupportHandler).ServeHTTP(w, r)
case strings.HasPrefix(r.URL.Path, "/api/tags"):
http.StripPrefix("/api", h.TagHandler).ServeHTTP(w, r)
case strings.HasPrefix(r.URL.Path, "/api/templates"):
diff --git a/api/http/handler/support/handler.go b/api/http/handler/support/handler.go
new file mode 100644
index 000000000..1ac8de22a
--- /dev/null
+++ b/api/http/handler/support/handler.go
@@ -0,0 +1,26 @@
+package support
+
+import (
+ "net/http"
+
+ httperror "github.com/portainer/libhttp/error"
+
+ "github.com/gorilla/mux"
+ "github.com/portainer/portainer/api/http/security"
+)
+
+// Handler is the HTTP handler used to handle support operations.
+type Handler struct {
+ *mux.Router
+}
+
+// NewHandler returns a new Handler
+func NewHandler(bouncer *security.RequestBouncer) *Handler {
+ h := &Handler{
+ Router: mux.NewRouter(),
+ }
+ h.Handle("/support",
+ bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.supportList))).Methods(http.MethodGet)
+
+ return h
+}
diff --git a/api/http/handler/support/support_list.go b/api/http/handler/support/support_list.go
new file mode 100644
index 000000000..a16d8dafd
--- /dev/null
+++ b/api/http/handler/support/support_list.go
@@ -0,0 +1,39 @@
+package support
+
+import (
+ "encoding/json"
+
+ httperror "github.com/portainer/libhttp/error"
+ portainer "github.com/portainer/portainer/api"
+
+ "net/http"
+
+ "github.com/portainer/portainer/api/http/client"
+
+ "github.com/portainer/libhttp/response"
+)
+
+type supportProduct struct {
+ ID int `json:"Id"`
+ Name string `json:"Name"`
+ ShortDescription string `json:"ShortDescription"`
+ Price string `json:"Price"`
+ PriceDescription string `json:"PriceDescription"`
+ Description string `json:"Description"`
+ ProductID string `json:"ProductId"`
+}
+
+func (handler *Handler) supportList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
+ supportData, err := client.Get(portainer.SupportProductsURL, 30)
+ if err != nil {
+ return &httperror.HandlerError{http.StatusInternalServerError, "Unable to fetch support options", err}
+ }
+
+ var supportProducts []supportProduct
+ err = json.Unmarshal(supportData, &supportProducts)
+ if err != nil {
+ return &httperror.HandlerError{http.StatusInternalServerError, "Unable to fetch support options", err}
+ }
+
+ return response.JSON(w, supportProducts)
+}
diff --git a/api/http/server.go b/api/http/server.go
index 664c1989f..40c11ac2e 100644
--- a/api/http/server.go
+++ b/api/http/server.go
@@ -3,6 +3,8 @@ package http
import (
"time"
+ "github.com/portainer/portainer/api/http/handler/support"
+
"github.com/portainer/portainer/api/http/handler/roles"
"github.com/portainer/portainer/api"
@@ -227,6 +229,8 @@ func (server *Server) Start() error {
var statusHandler = status.NewHandler(requestBouncer, server.Status)
+ var supportHandler = support.NewHandler(requestBouncer)
+
var templatesHandler = templates.NewHandler(requestBouncer)
templatesHandler.TemplateService = server.TemplateService
templatesHandler.SettingsService = server.SettingsService
@@ -268,6 +272,7 @@ func (server *Server) Start() error {
SettingsHandler: settingsHandler,
StatusHandler: statusHandler,
StackHandler: stackHandler,
+ SupportHandler: supportHandler,
TagHandler: tagHandler,
TeamHandler: teamHandler,
TeamMembershipHandler: teamMembershipHandler,
diff --git a/api/portainer.go b/api/portainer.go
index 7fdf39b5c..a50b0186a 100644
--- a/api/portainer.go
+++ b/api/portainer.go
@@ -914,6 +914,8 @@ const (
VersionCheckURL = "https://api.github.com/repos/portainer/portainer/releases/latest"
// ExtensionDefinitionsURL represents the URL where Portainer extension definitions can be retrieved
ExtensionDefinitionsURL = AssetsServerURL + "/extensions-1.22.0.json"
+ // SupportProductsURL represents the URL where Portainer support products can be retrieved
+ SupportProductsURL = AssetsServerURL + "/support.json"
// PortainerAgentHeader represents the name of the header available in any agent response
PortainerAgentHeader = "Portainer-Agent"
// PortainerAgentEdgeIDHeader represent the name of the header containing the Edge ID associated to an agent/agent cluster
diff --git a/app/constants.js b/app/constants.js
index d741e312d..8cbcbb9e8 100644
--- a/app/constants.js
+++ b/app/constants.js
@@ -11,6 +11,7 @@ angular.module('portainer')
.constant('API_ENDPOINT_SETTINGS', 'api/settings')
.constant('API_ENDPOINT_STACKS', 'api/stacks')
.constant('API_ENDPOINT_STATUS', 'api/status')
+.constant('API_ENDPOINT_SUPPORT', 'api/support')
.constant('API_ENDPOINT_USERS', 'api/users')
.constant('API_ENDPOINT_TAGS', 'api/tags')
.constant('API_ENDPOINT_TEAMS', 'api/teams')
diff --git a/app/portainer/rest/support.js b/app/portainer/rest/support.js
new file mode 100644
index 000000000..7fb3a5a90
--- /dev/null
+++ b/app/portainer/rest/support.js
@@ -0,0 +1,7 @@
+angular.module('portainer.app')
+.factory('Support', ['$resource', 'API_ENDPOINT_SUPPORT', function SupportFactory($resource, API_ENDPOINT_SUPPORT) {
+ 'use strict';
+ return $resource(API_ENDPOINT_SUPPORT, {}, {
+ get: { method: 'GET', isArray: true },
+ });
+}]);
diff --git a/app/portainer/services/api/supportService.js b/app/portainer/services/api/supportService.js
new file mode 100644
index 000000000..9bbcb56aa
--- /dev/null
+++ b/app/portainer/services/api/supportService.js
@@ -0,0 +1,21 @@
+angular.module('portainer.app')
+.factory('SupportService', ['$q', 'Support', function SupportServiceFactory($q, Support) {
+ 'use strict';
+ var service = {};
+
+ service.supportProducts = function() {
+ var deferred = $q.defer();
+
+ Support.get().$promise
+ .then(function success(data) {
+ deferred.resolve(data);
+ })
+ .catch(function error(err) {
+ deferred.reject({ msg: 'Unable to retrieve support options', err: err });
+ });
+
+ return deferred.promise;
+ };
+
+ return service;
+}]);
diff --git a/app/portainer/views/home/homeController.js b/app/portainer/views/home/homeController.js
index 78dc765d2..003f96edb 100644
--- a/app/portainer/views/home/homeController.js
+++ b/app/portainer/views/home/homeController.js
@@ -22,7 +22,7 @@ angular.module('portainer.app')
endpoint = data;
return switchToDockerEndpoint(endpoint);
}).catch(function error(err) {
- Notifications.error('Failure', err, 'Unable to verify endpoint status');
+ Notifications.error('Failure', err, 'Unable to verify endpoint status');
});
};
diff --git a/app/portainer/views/support/support.html b/app/portainer/views/support/support.html
index 97e0e3a7e..8bae72b91 100644
--- a/app/portainer/views/support/support.html
+++ b/app/portainer/views/support/support.html
@@ -6,23 +6,6 @@
-
- Business support is a subscription service and is delivered by Portainer developers directly. Portainer Business Support is available in Standard and Critical levels, which offer a range of availability and response time options.
-
- Once acquired through an in-app purchase, a support subscription will enable private access to the Portainer Support Portal at the appropriate service level.
-
- Business support includes comprehensive assistance and issue resolution for Portainer software, as well as the ability to ask “how to” questions.
-
- Issues outside Portainer (such as those relating to third party software or hardware) will be diagnosed, verified and the client will be referred to the relevant supplier for support. Portainer support will investigate and resolve any bugs that are identified as part of the support case.
-