diff --git a/CHANGES.md b/CHANGES.md
index e7b1a736..bb8355b0 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,7 @@
## Version 1.26
+- Restyle Org Limits
- Add new options to hide buttons in popup
## Version 1.25
diff --git a/addon/event-monitor.js b/addon/event-monitor.js
index d30221cd..fa1d2ead 100644
--- a/addon/event-monitor.js
+++ b/addon/event-monitor.js
@@ -53,9 +53,9 @@ class Model {
let channel = args.get("channel");
this.selectedChannel = channel;
this.selectedChannelType = channel.endsWith("__e") ? "platformEvent" : "standardPlatformEvent";
- } else if(args.get("channelType")){
- this.selectedChannelType = args.get("channelType")
- } else{
+ } else if (args.get("channelType")){
+ this.selectedChannelType = args.get("channelType");
+ } else {
this.selectedChannelType = channelTypes[0].value;
}
}
@@ -139,7 +139,7 @@ class App extends React.Component {
let channels = sessionChannel ? sessionChannel : [];
let query;
- if(channels.length == 0){
+ if (channels.length == 0){
if (channelType == "standardPlatformEvent"){
query = "SELECT Label, QualifiedApiName, DeveloperName FROM EntityDefinition"
+ " WHERE IsCustomizable = FALSE AND IsEverCreatable = TRUE"
@@ -151,18 +151,18 @@ class App extends React.Component {
+ " AND KeyPrefix LIKE 'e%' ORDER BY Label ASC";
}
await sfConn.rest("/services/data/v" + apiVersion + "/tooling/query?q=" + encodeURIComponent(query))
- .then(result => {
- result.records.forEach((channel) => {
- channels.push({
- name: channel.QualifiedApiName,
- label: channel.Label + " (" + channel.QualifiedApiName + ")"
+ .then(result => {
+ result.records.forEach((channel) => {
+ channels.push({
+ name: channel.QualifiedApiName,
+ label: channel.Label + " (" + channel.QualifiedApiName + ")"
+ });
});
+ })
+ .catch(err => {
+ console.error("An error occured fetching Event Channels of type " + channelType + ": ", err.message);
});
- })
- .catch(err => {
- console.error("An error occured fetching Event Channels of type " + channelType + ": ", err.message);
- });
- sessionStorage.setItem(sfHost + "_" + channelType, JSON.stringify(channels));
+ sessionStorage.setItem(sfHost + "_" + channelType, JSON.stringify(channels));
}
return channels;
}
@@ -201,25 +201,24 @@ class App extends React.Component {
model.selectedChannelType = e.target.value;
const urlParams = new URLSearchParams(window.location.search);
- urlParams.set('channelType', model.selectedChannelType);
- window.history.replaceState(null, '', '?' + urlParams.toString());
+ urlParams.set("channelType", model.selectedChannelType);
+ window.history.replaceState(null, "", "?" + urlParams.toString());
this.getEventChannels();
model.didUpdate();
}
onChannelSelection(e) {
- let { model } = this.props;
+ let {model} = this.props;
model.selectedChannel = e.target.value;
const urlParams = new URLSearchParams(window.location.search);
- urlParams.set('channel', model.selectedChannel);
- window.history.replaceState(null, '', '?' + urlParams.toString());
+ urlParams.set("channel", model.selectedChannel);
+ window.history.replaceState(null, "", "?" + urlParams.toString());
model.didUpdate();
}
-
onReplayIdChange(e) {
let {model} = this.props;
model.replayId = e.target.value;
@@ -253,7 +252,7 @@ class App extends React.Component {
//Load Salesforce Replay Extension
let replayExtension = new cometdReplayExtension();
- replayExtension.setChannel(channelSuffix +model.selectedChannel);
+ replayExtension.setChannel(channelSuffix + model.selectedChannel);
replayExtension.setReplay(model.replayId);
replayExtension.setExtensionEnabled = true;
cometd.registerExtension("SalesforceReplayExtension", replayExtension);
diff --git a/addon/limits.css b/addon/limits.css
index 184c39b2..5bbe8647 100644
--- a/addon/limits.css
+++ b/addon/limits.css
@@ -30,13 +30,13 @@ figcaption > div {
display:block;
content:"";
}
-.gauge:before, .meter {
- width:10rem;
- height:5rem;
+.gauge:before, .meter {
+ width:10rem;
+ height:5rem;
}
-.gauge:before {
- border-radius:5rem 5rem 0 0;
- background:grey;
+.gauge:before {
+ border-radius:5rem 5rem 0 0;
+ background:grey;
}
.gauge:after {
position:absolute;
@@ -86,29 +86,6 @@ body {
font-size: 11px;
margin: 0;
}
-.sf-link {
- margin-right: 1em;
- background-color: rgb(6, 28, 63);
- border-radius: 3px;
- line-height: 2em;
- text-decoration: none;
- display: inline-block;
- padding: 2px;
- color: white;
- padding-right: 1em;
-}
-.sf-link svg {
- width: 2em;
- height: 2em;
- display: block;
- margin-left: 1px;
- margin-right: 1em;
- float: left;
- background-color: #ef7ead;
- border-radius: 2px;
- fill: white;
-}
-
.error-message {
font-size: 1.2em;
@@ -176,4 +153,9 @@ body {
.body.empty {
animation: spin 4s linear infinite;
}
-
+#user-info {
+ font-size: .8125rem;
+}
+#user-info span {
+ font-size: 1em;
+}
\ No newline at end of file
diff --git a/addon/limits.html b/addon/limits.html
index 5f4405c2..32918e22 100644
--- a/addon/limits.html
+++ b/addon/limits.html
@@ -1,16 +1,22 @@
-
-
- ...
-
-
-
-
-
-
-
-
-
-
+
+
+
+ ...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addon/limits.js b/addon/limits.js
index c4b28d90..472350c0 100644
--- a/addon/limits.js
+++ b/addon/limits.js
@@ -1,5 +1,6 @@
/* global React ReactDOM */
import {sfConn, apiVersion} from "./inspector.js";
+import {copyToClipboard} from "./data-load.js";
/* global initButton */
class Model {
@@ -7,8 +8,17 @@ class Model {
this.reactCallback = null;
this.sfLink = "https://" + sfHost;
this.spinnerCount = 0;
+ this.title = "Org Limits";
+ this.userInfo = "...";
this.allLimitData = [];
this.errorMessages = [];
+ this.sortOptions = [{label: "Consumption", value: "consumption"}, {label: "A-Z %", value: "asc"}];
+ this.sortBy = this.sortOptions[1];
+
+ let userInfoPromise = sfConn.soap(sfConn.wsdl(apiVersion, "Partner"), "getUserInfo", {});
+ this.spinFor("userInfo", userInfoPromise, (res) => {
+ this.userInfo = res.userFullName + " / " + res.userName + " / " + res.organizationName;
+ });
}
didUpdate(cb) {
@@ -34,10 +44,6 @@ class Model {
.catch(err => console.log("error handling failed", err));
}
- title() {
- return "Org Limits";
- }
-
setLimitsData(res) {
let self = this;
this.allLimitData = [];
@@ -48,7 +54,8 @@ class Model {
"label": self.humanizeName(key),
"description": "...",
"max": res[key].Max,
- "remaining": res[key].Remaining
+ "remaining": res[key].Remaining,
+ "consumption": (res[key].Max - res[key].Remaining) / res[key].Max
});
});
}
@@ -64,6 +71,10 @@ class Model {
this.setLimitsData(res);
});
}
+
+ copyAsJson() {
+ copyToClipboard(JSON.stringify(this.allLimitData ? this.allLimitData : this.allLimitData, null, " "), null, " ");
+ }
}
@@ -116,39 +127,79 @@ class LimitData extends React.Component {
}
class App extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.model = this.props.vm;
+ this.onCopyAsJson = this.onCopyAsJson.bind(this);
+ this.onSortBy = this.onSortBy.bind(this);
+ }
+
+ sortLimits(data, sortBy) {
+ const sortFunctions = {
+ consumption: (a, b) => b.consumption - a.consumption,
+ asc: (a, b) => a.label.localeCompare(b.label)
+ };
+ return data.sort(sortFunctions[sortBy] || (() => 0));
+ }
+
+ onCopyAsJson() {
+ this.model.copyAsJson();
+ this.model.didUpdate();
+ }
+ onSortBy(e){
+ this.model.sortBy = e.target.value;
+ this.model.allLimitData = this.sortLimits(this.model.allLimitData, this.model.sortBy);
+ this.model.didUpdate();
+ }
+
render() {
- let vm = this.props.vm;
- document.title = vm.title();
- return (
- h("div", {},
- h("div", {
- className: "object-bar"
- },
- h("img", {
- id: "spinner",
- src: "data:image/gif;base64,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",
- hidden: vm.spinnerCount == 0
- }),
- h("a", {
- href: vm.sfLink,
- className: "sf-link"
- },
- h("svg", {
- viewBox: "0 0 24 24"
- },
- h("path", {
- d: "M18.9 12.3h-1.5v6.6c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-5.1h-3.6v5.1c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-6.6H5.1c-.1 0-.3-.1-.3-.2s0-.2.1-.3l6.9-7c.1-.1.3-.1.4 0l7 7v.3c0 .1-.2.2-.3.2z"
- })
+ let model = this.props.vm;
+ document.title = model.title;
+ return h("div", {},
+ h("div", {id: "user-info"},
+ h("a", {href: `https://${sfConn.instanceHostname}`, className: "sf-link"},
+ h("svg", {viewBox: "0 0 24 24"},
+ h("path", {d: "M18.9 12.3h-1.5v6.6c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-5.1h-3.6v5.1c0 .2-.1.3-.3.3h-3c-.2 0-.3-.1-.3-.3v-6.6H5.1c-.1 0-.3-.1-.3-.2s0-.2.1-.3l6.9-7c.1-.1.3-.1.4 0l7 7v.3c0 .1-.2.2-.3.2z"})
+ ),
+ " Salesforce Home"
),
- " Salesforce Home"
- )
+ h("h1", {}, model.title),
+ h("span", {}, " / " + model.userInfo),
+ h("div", {className: "flex-right"},
+ h("a", {href: "https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_limits.htm", target: "_blank", id: "help-btn", title: "Org Limits Help", onClick: null},
+ h("div", {className: "icon"})
+ ),
+ h("div", {id: "spinner", role: "status", className: "slds-spinner slds-spinner_small slds-spinner_inline", hidden: model.spinnerCount == 0},
+ h("span", {className: "slds-assistive-text"}),
+ h("div", {className: "slds-spinner__dot-a"}),
+ h("div", {className: "slds-spinner__dot-b"}),
+ ),
),
- h("div", {
- className: "body"
- },
- vm.allLimitData.map(limitData =>
- h(LimitData, limitData)
- )
+ ),
+ h("div", {className: "area", id: "result-area"},
+ h("div", {className: "result-bar"},
+ h("h1", {}, "Limits"),
+ h("div", {className: "button-group"},
+ h("button", {disabled: model.allLimitData.length == 0, onClick: this.onCopyAsJson, title: "Copy raw JSON to clipboard"}, "Copy")
+ ),
+ h("div", {className: "flex-right"},
+ h("select", {value: model.sortBy, onChange: this.onSortBy, className: ""},
+ h("option", {value: "none", disabled: true, defaultValue: true, hidden: true}, "Sort By"),
+ model.sortOptions.map(opt => h("option", {key: opt.value, value: opt.value}, opt.label))
+ ),
+ ),
+ ),
+ h("div", {id: "result-table", ref: "scroller"},
+ h("div", {},
+ h("div", {
+ className: "body"
+ },
+ model.allLimitData.map(limitData =>
+ h(LimitData, limitData)
+ )
+ )
+ )
)
)
);