mirror of https://github.com/portainer/portainer
feat(app): add externally sourced support options (#3249)
* feat(app): add externally sourced support options * refactor(api): rename struct fieldspull/3255/head
parent
521a36e629
commit
ab2acea463
|
@ -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"):
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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 },
|
||||
});
|
||||
}]);
|
|
@ -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;
|
||||
}]);
|
|
@ -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');
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -6,23 +6,6 @@
|
|||
</rd-header-content>
|
||||
</rd-header>
|
||||
|
||||
<information-panel title-text="Information">
|
||||
<span class="small text-muted">
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
Once acquired through an in-app purchase, a support subscription will enable private access to the Portainer Support Portal at the appropriate service level.
|
||||
</p>
|
||||
<p>
|
||||
Business support includes comprehensive assistance and issue resolution for Portainer software, as well as the ability to ask “how to” questions.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</span>
|
||||
</information-panel>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<product-list
|
||||
|
|
|
@ -1,34 +1,20 @@
|
|||
angular.module('portainer.app')
|
||||
.controller('SupportController', ['$scope', '$state',
|
||||
function($scope, $state) {
|
||||
.controller('SupportController', ['$scope', '$state', 'SupportService', 'Notifications',
|
||||
function($scope, $state, SupportService, Notifications) {
|
||||
|
||||
$scope.goToProductView = function(product) {
|
||||
$state.go('portainer.support.product', { product: product });
|
||||
};
|
||||
|
||||
function initView() {
|
||||
var supportProducts = [
|
||||
{
|
||||
Id: 1,
|
||||
Name: 'Business Support Standard',
|
||||
ShortDescription: '11x5 support with 4 hour response',
|
||||
Price: 'US$120.00',
|
||||
PriceDescription: 'Price per month per host (minimum 10 hosts)',
|
||||
Description: 'Portainer Business Support Standard:\n\n* 7am – 6pm business days, local time.\n* 4 Hour response for issues, 4 named support contacts.\n\nPortainer support provides you with an easy way to interact directly with the Portainer development team; whether you have an issue with the product, think you have found a bug, or need help on how to use Portainer, we are here to help. Support is initiated from our web based ticketing system, and support is provided either by Slack messaging, Zoom remote support, or email.\n\nPrice is per Docker Host, with a 10 Host minimum, and is an annual support subscription.',
|
||||
ProductId: '1163'
|
||||
},
|
||||
{
|
||||
Id: 2,
|
||||
Name: 'Business Support Critical',
|
||||
ShortDescription: '24x7 support with 1 hour response',
|
||||
Price: 'US$240.00',
|
||||
PriceDescription: 'Price per month per host (minimum 10 hosts)',
|
||||
Description: 'Portainer Business Support Critical:\n\n* 24x7\n* 1 Hour response for issues, 4 named support contacts.\n\nPortainer support provides you with advanced support for critical requirements. Business Support Critical is an easy way to interact directly with the Portainer development team; whether you have an issue with the product, think you have found a bug, or need help on how to use Portainer, we are here to help. Support is initiated from our web based ticketing system, and support is provided either by Slack messaging, Zoom remote support, or email.\n\nPrice is per Docker Host, with a 10 Host minimum, and is an annual support subscription.',
|
||||
ProductId: '1162'
|
||||
}
|
||||
];
|
||||
|
||||
$scope.products = supportProducts;
|
||||
SupportService.supportProducts()
|
||||
.then(function success(data){
|
||||
$scope.products = data;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to fetch support options');
|
||||
});
|
||||
}
|
||||
|
||||
initView();
|
||||
|
|
Loading…
Reference in New Issue