-
-
Notifications
You must be signed in to change notification settings - Fork 337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new admin toggle for turning Enterprise on and off #1095
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
eded090
Dockerfile: silence a warning
jordigh 566d873
config: end the file with a newline
jordigh 6562988
configCore: default to enterprise edition if TEST_ENABLE_ACTIVATION i…
jordigh 089b37f
config: new API endpoint
jordigh d8a4d32
ToggleEnterpriseModel: new GrainJS model to handle changes to config API
jordigh 6bc4e67
FlexServer: remove config from restart endpoint
jordigh 57e50ca
supervisor: remove config stub
jordigh f9a0519
AdminToggleCss: factor out CSS from SupportGristPage
jordigh 48c872f
restart: gracefully handle restart failure
jordigh 35b2516
ConfigAPI: new class to handle frontend requests to config backend
jordigh d0d9150
markdown: new utility module
jordigh a6b26d4
ToggleEnterpriseWidget: new frontend toggle for the admin
jordigh ee716ae
AdminPanel: add the toggle for enterprise
jordigh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { sanitizeHTML } from 'app/client/ui/sanitizeHTML'; | ||
import { BindableValue, DomElementMethod, subscribeElem } from 'grainjs'; | ||
import { marked } from 'marked'; | ||
|
||
export function markdown(markdownObs: BindableValue<string>): DomElementMethod { | ||
return elem => subscribeElem(elem, markdownObs, value => setMarkdownValue(elem, value)); | ||
} | ||
|
||
function setMarkdownValue(elem: Element, markdownValue: string): void { | ||
elem.innerHTML = sanitizeHTML(marked(markdownValue)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import {getHomeUrl} from 'app/client/models/AppModel'; | ||
import {Disposable, Observable} from "grainjs"; | ||
import {ConfigAPI} from 'app/common/ConfigAPI'; | ||
import {delay} from 'app/common/delay'; | ||
|
||
export class ToggleEnterpriseModel extends Disposable { | ||
jordigh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public readonly edition: Observable<string | null> = Observable.create(this, null); | ||
private readonly _configAPI: ConfigAPI = new ConfigAPI(getHomeUrl()); | ||
|
||
public async fetchEnterpriseToggle(): Promise<void> { | ||
const edition = await this._configAPI.getValue('edition'); | ||
this.edition.set(edition); | ||
} | ||
|
||
public async updateEnterpriseToggle(edition: string): Promise<void> { | ||
// We may be restarting the server, so these requests may well | ||
// fail if done in quick succession. | ||
await retryOnNetworkError(() => this._configAPI.setValue({edition})); | ||
this.edition.set(edition); | ||
await retryOnNetworkError(() => this._configAPI.restartServer()); | ||
} | ||
} | ||
|
||
// Copied from DocPageModel.ts | ||
const reconnectIntervals = [1000, 1000, 2000, 5000, 10000]; | ||
async function retryOnNetworkError<R>(func: () => Promise<R>): Promise<R> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not great to have copies of retry code that get independent fixes, but also ok given schedule. Hmm might be a bit weird if multiple requests overlap, there's no cancellation. It is acceptable, given what it is. |
||
for (let attempt = 0; ; attempt++) { | ||
try { | ||
return await func(); | ||
} catch (err) { | ||
// fetch() promises that network errors are reported as TypeError. We'll accept NetworkError too. | ||
if (err.name !== "TypeError" && err.name !== "NetworkError") { | ||
throw err; | ||
} | ||
// We really can't reach the server. Make it known. | ||
if (attempt >= reconnectIntervals.length) { | ||
throw err; | ||
} | ||
const reconnectTimeout = reconnectIntervals[attempt]; | ||
console.warn(`Call to ${func.name} failed, will retry in ${reconnectTimeout} ms`, err); | ||
await delay(reconnectTimeout); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import {bigBasicButton, bigBasicButtonLink, bigPrimaryButton} from 'app/client/ui2018/buttons'; | ||
import {theme} from 'app/client/ui2018/cssVars'; | ||
import {styled} from 'grainjs'; | ||
|
||
export const cssSection = styled('div', ``); | ||
|
||
export const cssParagraph = styled('div', ` | ||
color: ${theme.text}; | ||
font-size: 14px; | ||
line-height: 20px; | ||
margin-bottom: 12px; | ||
`); | ||
|
||
export const cssOptInOutMessage = styled(cssParagraph, ` | ||
line-height: 40px; | ||
font-weight: 600; | ||
margin-top: 24px; | ||
margin-bottom: 0px; | ||
`); | ||
|
||
export const cssOptInButton = styled(bigPrimaryButton, ` | ||
margin-top: 24px; | ||
`); | ||
|
||
export const cssOptOutButton = styled(bigBasicButton, ` | ||
margin-top: 24px; | ||
`); | ||
|
||
export const cssSponsorButton = styled(bigBasicButtonLink, ` | ||
margin-top: 24px; | ||
`); | ||
|
||
export const cssButtonIconAndText = styled('div', ` | ||
display: flex; | ||
align-items: center; | ||
`); | ||
|
||
export const cssButtonText = styled('span', ` | ||
margin-left: 8px; | ||
`); | ||
|
||
export const cssSpinnerBox = styled('div', ` | ||
margin-top: 24px; | ||
text-align: center; | ||
`); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import {makeT} from 'app/client/lib/localization'; | ||
import {markdown} from 'app/client/lib/markdown'; | ||
import {Computed, Disposable, dom, makeTestId} from "grainjs"; | ||
import {commonUrls} from "app/common/gristUrls"; | ||
import {ToggleEnterpriseModel} from 'app/client/models/ToggleEnterpriseModel'; | ||
import { | ||
cssOptInButton, | ||
cssOptOutButton, | ||
cssParagraph, | ||
cssSection, | ||
} from 'app/client/ui/AdminTogglesCss'; | ||
|
||
|
||
const t = makeT('ToggleEnterprsiePage'); | ||
const testId = makeTestId('test-toggle-enterprise-page-'); | ||
|
||
export class ToggleEnterpriseWidget extends Disposable { | ||
private readonly _model: ToggleEnterpriseModel = new ToggleEnterpriseModel(); | ||
private readonly _isEnterprise = Computed.create(this, this._model.edition, (_use, edition) => { | ||
return edition === 'enterprise'; | ||
}).onWrite(async (enabled) => { | ||
await this._model.updateEnterpriseToggle(enabled ? 'enterprise' : 'core'); | ||
}); | ||
|
||
constructor() { | ||
super(); | ||
this._model.fetchEnterpriseToggle().catch(reportError); | ||
} | ||
|
||
public getEnterpriseToggleObservable() { | ||
return this._isEnterprise; | ||
} | ||
|
||
public buildEnterpriseSection() { | ||
return cssSection( | ||
dom.domComputed(this._isEnterprise, (enterpriseEnabled) => { | ||
return [ | ||
enterpriseEnabled ? | ||
cssParagraph( | ||
markdown(t('Grist Enterprise is **enabled**.')), | ||
testId('enterprise-opt-out-message'), | ||
) : null, | ||
cssParagraph( | ||
markdown(t(`An activation key is used to run Grist Enterprise after a trial period | ||
of 30 days has expired. Get an activation key by [signing up for Grist | ||
Enterprise]({{signupLink}}). You do not need an activation key to run | ||
Grist Core. | ||
|
||
Learn more in our [Help Center]({{helpCenter}}).`, { | ||
signupLink: commonUrls.plans, | ||
helpCenter: commonUrls.helpEnterpriseOptIn | ||
})) | ||
), | ||
this._buildEnterpriseSectionButtons(), | ||
]; | ||
}), | ||
testId('enterprise-opt-in-section'), | ||
); | ||
} | ||
|
||
public _buildEnterpriseSectionButtons() { | ||
return dom.domComputed(this._isEnterprise, (enterpriseEnabled) => { | ||
if (enterpriseEnabled) { | ||
return [ | ||
cssOptOutButton(t('Disable Grist Enterprise'), | ||
dom.on('click', () => this._isEnterprise.set(false)), | ||
), | ||
]; | ||
} else { | ||
return [ | ||
cssOptInButton(t('Enable Grist Enterprise'), | ||
dom.on('click', () => this._isEnterprise.set(true)), | ||
), | ||
]; | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import {BaseAPI, IOptions} from "app/common/BaseAPI"; | ||
import {addCurrentOrgToPath} from 'app/common/urlUtils'; | ||
|
||
/** | ||
* An API for accessing the internal Grist configuration, stored in | ||
* config.json. | ||
*/ | ||
export class ConfigAPI extends BaseAPI { | ||
constructor(private _homeUrl: string, options: IOptions = {}) { | ||
super(options); | ||
} | ||
|
||
public async getValue(key: string): Promise<any> { | ||
return (await this.requestJson(`${this._url}/api/config/${key}`, {method: 'GET'})).value; | ||
} | ||
|
||
public async setValue(value: any, restart=false): Promise<void> { | ||
await this.request(`${this._url}/api/config`, { | ||
method: 'PATCH', | ||
body: JSON.stringify({config: value, restart}), | ||
}); | ||
} | ||
|
||
public async restartServer(): Promise<void> { | ||
await this.request(`${this._url}/api/admin/restart`, {method: 'POST'}); | ||
jordigh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
private get _url(): string { | ||
return addCurrentOrgToPath(this._homeUrl); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments around purpose would be useful for these two methods.