mirror of
https://github.com/portainer/portainer.git
synced 2025-07-30 10:49:40 +02:00
feat(app): add externally sourced support options (#3249)
* feat(app): add externally sourced support options * refactor(api): rename struct fields
This commit is contained in:
parent
521a36e629
commit
ab2acea463
11 changed files with 116 additions and 41 deletions
|
@ -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"):
|
||||
|
|
26
api/http/handler/support/handler.go
Normal file
26
api/http/handler/support/handler.go
Normal file
|
@ -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
|
||||
}
|
39
api/http/handler/support/support_list.go
Normal file
39
api/http/handler/support/support_list.go
Normal file
|
@ -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')
|
||||
|
|
7
app/portainer/rest/support.js
Normal file
7
app/portainer/rest/support.js
Normal file
|
@ -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 },
|
||||
});
|
||||
}]);
|
21
app/portainer/services/api/supportService.js
Normal file
21
app/portainer/services/api/supportService.js
Normal file
|
@ -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;
|
||||
}]);
|
|
@ -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…
Add table
Add a link
Reference in a new issue