settings_playground: Add UI to create a new playground.

The design of the form is similar to the linkifiers page
and is styled similarly.

The introduction text for "Code playgrounds" is improved
with more details and examples.

Also, we can remove the hardcoded playground and the fix
we had previously done to prevent breaking the hardcoded
playground.
This commit is contained in:
Sumanth V Rao
2021-04-17 15:09:02 +05:30
committed by Tim Abbott
parent e481f0c869
commit a510dac024
7 changed files with 119 additions and 64 deletions

View File

@@ -1,6 +1,3 @@
import {page_params} from "./page_params";
import * as settings_config from "./settings_config";
const map_language_to_playground_info = new Map();
export function update_playgrounds(playgrounds_data) {
@@ -21,16 +18,9 @@ export function update_playgrounds(playgrounds_data) {
}
export function get_playground_info_for_languages(lang) {
if (page_params.realm_playgrounds) {
return map_language_to_playground_info.get(lang);
}
// FIXME: To avoid breaking the configured hardcoded playgrounds, this approach
// is used. This will be removed in the commit which adds the UI for playground
// creation.
return settings_config.get_playground_info_for_languages(lang);
}
export function initialize(playground_data) {
update_playgrounds(playground_data);
}

View File

@@ -417,55 +417,6 @@ export const all_notifications = () => ({
},
});
const map_language_to_playground_info = {
// TODO: This is being hardcoded just for the prototype, post which we should
// add support for realm admins to configure their own choices. The keys here
// are the pygment lexer subclass names for the different language alias it
// supports.
Rust: [
{
name: "Rust playground",
url_prefix: "https://play.rust-lang.org/?edition=2018&code=",
},
],
Julia: [
{
name: "Julia playground",
url_prefix: "https://repl.it/languages/julia/?code=",
},
],
Python: [
{
name: "Python 3 playground",
url_prefix: "https://repl.it/languages/python3/?code=",
},
],
"Python 2.7": [
{
name: "Python 2.7 playground",
url_prefix: "https://repl.it/languages/python/?code=",
},
],
JavaScript: [
{
name: "JavaScript playground",
url_prefix: "https://repl.it/languages/javascript/?code=",
},
],
Lean: [
{
name: "Lean playground",
url_prefix: "https://leanprover.github.io/live/latest/#code=",
},
{
name: "Lean community playground",
url_prefix: "https://leanprover-community.github.io/lean-web-editor/#code=",
},
],
};
export const get_playground_info_for_languages = (lang) => map_language_to_playground_info[lang];
export const desktop_icon_count_display_values = {
messages: {
code: 1,

View File

@@ -2,9 +2,12 @@ import $ from "jquery";
import render_admin_playground_list from "../templates/settings/admin_playground_list.hbs";
import * as channel from "./channel";
import {$t_html} from "./i18n";
import * as ListWidget from "./list_widget";
import {page_params} from "./page_params";
import * as ui from "./ui";
import * as ui_report from "./ui_report";
const meta = {
loaded: false,
@@ -84,4 +87,49 @@ export function set_up() {
function build_page() {
meta.loaded = true;
populate_playgrounds(page_params.realm_playgrounds);
$(".organization form.admin-playground-form")
.off("submit")
.on("submit", function (e) {
e.preventDefault();
e.stopPropagation();
const playground_status = $("#admin-playground-status");
const add_playground_button = $(".new-playground-form button");
add_playground_button.prop("disabled", true);
playground_status.hide();
channel.post({
url: "/json/realm/playgrounds",
data: $(this).serialize(),
success() {
$("#playground_pygments_language").val("");
$("#playground_name").val("");
$("#playground_url_prefix").val("");
add_playground_button.prop("disabled", false);
ui_report.success(
$t_html({defaultMessage: "Custom playground added!"}),
playground_status,
3000,
);
// FIXME: One thing to note here is that the "view code in playground"
// option for an already rendered code block (tagged with this newly added
// language) would not be visible without a re-render. To fix this, we should
// probably do some extraction in `rendered_markdown.js` which does a
// live-update of the `data-code-language` parameter in code blocks. Or change
// how we do the HTML in the frontend so that the icon labels/behavior are
// computed dynamically when you hover over the message based on configured
// playgrounds. Since this isn't high priority right now, we can probably
// take this up later.
},
error(xhr) {
add_playground_button.prop("disabled", false);
ui_report.error(
$t_html({defaultMessage: "Failed"}),
xhr,
playground_status,
3000,
);
},
});
});
}

View File

@@ -194,6 +194,14 @@ h3 .fa-question-circle-o {
}
}
#playground-settings {
#playground_pygments_language,
#playground_name,
#playground_url_prefix {
width: calc(100% - 10em - 6em);
}
}
td .button {
margin: 2px 0;
box-shadow: none;
@@ -669,7 +677,8 @@ input[type="checkbox"] {
}
.add-new-profile-field-box,
.add-new-linkifier-box {
.add-new-linkifier-box,
.add-new-playground-box {
button {
margin-left: calc(10em + 20px) !important;
}
@@ -892,6 +901,7 @@ input[type="checkbox"] {
#create_alert_word_form,
.admin-emoji-form,
.admin-linkifier-form,
.admin-playground-form,
.admin-profile-field-form,
.edit_bot_form {
.control-label {
@@ -1867,11 +1877,13 @@ body:not(.night-mode) #settings_page .custom_user_field .datepicker {
}
#linkifier-settings .new-linkifier-form,
#playground-settings .new-playground-form,
#profile-field-settings .new-profile-field-form {
width: 100%;
}
#linkifier-settings .new-linkifier-form .control-label,
#playground-settings .new-playground-form .control-label,
#profile-field-settings .new-profile-field-form .control-label {
display: block;
width: 120px;
@@ -1883,6 +1895,7 @@ body:not(.night-mode) #settings_page .custom_user_field .datepicker {
}
#linkifier-settings .new-linkifier-form .controls,
#playground-settings .new-playground-form .controls,
#profile-field-settings .new-profile-field-form .controls {
margin: auto;
text-align: center;

View File

@@ -89,6 +89,11 @@ pre {
*/
height: 0 !important;
}
/* If the text in the tooltips stretches to multiple lines,
* we want the lines to be left-indented and not right-indented
* by default.
*/
text-align: left;
}
.no-select {

View File

@@ -2,10 +2,53 @@
<div class="admin-table-wrapper">
<p>
{{#tr}}
Configure external sites that can run code present in a Zulip code block.
Configure external code playgrounds for your Zulip organization. Code playgrounds are interactive in-browser development
environments, such as <z-link-repl>replit</z-link-repl>, that are designed to make it convenient to edit and debug
code. Zulip code blocks that are <z-link-markdown-help>tagged with a programming language</z-link-markdown-help> will have
a button visible on hover that allows you to open the code block in the code playground site.
{{#*inline "z-link-repl"}}<a href="https://replit.com/" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{#*inline "z-link-markdown-help"}}<a href="/help/format-your-message-using-markdown#code" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
<input type="text" class="search" placeholder="{{t 'Filter playgrounds' }}" aria-label="{{t 'Filter playgrounds' }}"/>
<p>
{{#tr}}
For example, to configure code playgrounds for languages like Python or JavaScript, you could specify the <i>Language</i>
and <i>URL Prefix</i> fields as:
{{/tr}}
</p>
<ul>
<li><code>Python</code> {{t "and" }} <code>https://replit.com/languages/python3/?code=</code></li>
<li><code>JavaScript</code> {{t "and" }} <code>https://replit.com/languages/javascript/?code=</code></li>
</ul>
{{#if is_admin}}
<form class="form-horizontal admin-playground-form">
<div class="add-new-playground-box grey-box">
<div class="new-playground-form wrapper">
<div class="settings-section-title">{{t "Add a new code playground" }}</div>
<div class="alert" id="admin-playground-status"></div>
<div class="control-group">
{{!-- TODO: This should have a typeahead suggestion popover --}}
<label for="playground_pygments_language" class="control-label"> {{t "Language" }}</label>
<input type="text" id="playground_pygments_language" name="pygments_language" autocomplete="off" placeholder="Python" />
</div>
<div class="control-group">
<label for="playground_name" class="control-label"> {{t "Name" }}</label>
<input type="text" id="playground_name" name="name" placeholder="Python3 playground" />
</div>
<div class="control-group">
<label for="playground_url_prefix" class="control-label"> {{t "URL prefix" }}</label>
<input type="text" id="playground_url_prefix" name="url_prefix" placeholder="https://replit.com/languages/python3/?code=" />
</div>
<button type="submit" class="button rounded sea-green">
{{t 'Add code playground' }}
</button>
</div>
</div>
</form>
{{/if}}
<input type="text" class="search" placeholder="{{t 'Filter code playgrounds' }}" aria-label="{{t 'Filter code playgrounds' }}"/>
<div class="progressive-table-wrapper" data-simplebar>
<table class="table table-condensed table-striped wrapped-table admin_playgrounds_table">
<thead>

View File

@@ -546,7 +546,12 @@ html_rules: List["Rule"] = [
("templates/zerver/register.html", 'placeholder="acme"'),
("templates/zerver/register.html", 'placeholder="Acme or Ακμή"'),
},
"exclude": {"templates/analytics/support.html"},
"exclude": {
"templates/analytics/support.html",
# We have URL prefix and Pygments language name as placeholders
# in the below template which we don't want to be translatable.
"static/templates/settings/playground_settings_admin.hbs",
},
"good_lines": [
'<input class="stream-list-filter" type="text" placeholder="{{ _(\'Filter streams\') }}" />'
],