/
vshmidt
/
label-studio
Обзор
Документация
Войти
/
vshmidt
/
label-studio
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
docs/source/playground/index.ejs
694 строки
15 KB
bmartel
fix: FIT-155: Launch in playground doesn't load config from URL (#7611)
23 май 2025, 18:19
Не верифицирован
23 май 2025, 18:19
d6693e7
Код
Авторство
О чём код?
--- type: playground order: 201 meta_title: Data Labeling & Annotation Tool Interactive Demo meta_description: Label Studio interactive demo and playground for data labeling and annotation for machine learning and data science projects. --- <script src="https://code.jquery.com/jquery-3.7.0.min.js" integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous"></script> <style> .page-type-playground .content-grid { display: block; } .page-type-playground .container { max-width: 110rem; padding: 1em 2.5rem; } .page-type-playground .content-footer { max-width: 1030px; margin: 4em auto; } @media (max-width: 1100px) { .page-type-playground .content-footer { padding-left: 1em; padding-right: 1em; } .page-type-playground .container { padding: 1em; } } .content { max-width: none !important; margin-left: 0 !important; padding: 1em 0 0 0; } .validation { margin-top: 1em; margin-left: 1em; color: red; text-transform: capitalize; } .CodeMirror { min-height: 500px !important; } h1 { margin-bottom: 0.5em !important; } h3 { margin: 1em 0 !important; font-weight: normal; width: unset; height: unset; } iframe { border: 0; margin: 0 !important; padding: 0 !important; } #render-editor { width: 100%; } #editor-wrap { padding: 0; margin: 0; display: none; } .preview { padding: 5px; overflow: auto; white-space: pre; } .editor-row { display: flex; margin: 0 auto 1.5em; width: 100% !important; max-width: 110rem; } .intro-wrapper{ background: white; border: 1px solid var(--color-gray-300); border-radius: .75rem; padding: 1.5rem; max-width: 110rem; margin: 0 auto 1.5rem; } .data-row { display: flex; max-width: 110rem; margin: 0 auto; background: white; border: 1px solid var(--color-gray-300); border-radius: .75rem; padding: 1.5rem; } .preview-col { width: 60%; flex: 1; background: white; border: 1px solid var(--color-gray-300); border-radius: .75rem; padding: 1.5rem; } .editor-area { border: 1px solid rgba(34,36,38,.15); border-radius: .5rem; overflow: hidden; } .config-col p{ margin: .75rem 0 0 0; color: var(--color-gray-600); } .config-col { margin-right: 1.5em; width: 40%; background: white; border: 1px solid var(--color-gray-300); border-radius: .75rem; padding: 1.5rem; } .config-wrapper{ display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; } .config-wrapper h4{ margin-top: 0; margin-bottom: 0; } .input-col { width: 49%; padding-right: 2%; } .output-col { width: 49%; } .hidden { display: none !important; } h4 { margin-bottom: 1rem; margin-top: 0 !important; } /* hide title "basic template configs" */ #basic-templates>.title { display: none; } #adv-templates>.title { margin-bottom: 1em; cursor: pointer; } #adv-templates>.content { display: none } .message, .accordion { margin-top: .5rem; } .grid { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; -ms-flex-wrap: wrap; flex-wrap: wrap; -webkit-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; padding: 0; } .loading{ display: flex; flex-direction: column; align-items: center; } .loading img{ border: none; } .column { width: 20% !important; } .use-template { font-weight: normal!important; margin-bottom: .5rem; display: block; } @font-face { font-family: 'Icons'; src: url("/fonts/icons.eot"); src: url("/fonts/icons.eot?#iefix") format('embedded-opentype'), url("/fonts/icons.woff2") format('woff2'), url("/fonts/icons.woff") format('woff'), url("/fonts/icons.ttf") format('truetype'), url("/fonts/icons.svg#icons") format('svg'); font-style: normal; font-weight: normal; font-variant: normal; text-decoration: inherit; text-transform: none; } i.icon { opacity: 0.75; display: inline-block; margin: 0 0 0 0; width: 1.18em; height: 1em; font-family: 'Icons'; font-style: normal; font-weight: normal; text-decoration: inherit; text-align: center; speak: none; -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; -webkit-backface-visibility: hidden; backface-visibility: hidden; } i.icon + .ui{ margin-top: .75rem; } i.icon:before { background: none !important; } i.icon.sound:before { content: "\f025"; } i.icon.image:before { content: "\f03e"; } i.icon.code:before { content: "\f121"; } i.icon.font:before { content: "\f031"; } i.icon.video:before { content: "\f03d"; } i.icon.share:before { content: "\f064" } i.icon.copy.outline:before { content: "\f0c5" } i.icon.archive:before { content: "\f187"; } i.icon.eye:before { content: "\f06e"; } i.icon.bullseye:before { content: "\f140"; } i.icon.vector.square:before { content: "\f5cb"; } i.icon.wave.square:before { content: "\f83e" } i.icon.dropdown:before { content: "\f0da"; } i.icon.dropdown.active:before { content: "\f0d7"; } .share-buttons { float:right; margin: 0 0 0 1em; } .share-buttons i { cursor: pointer; color: var(--color-orange-400); transition: 0.25s; } .share-buttons i:hover { opacity: 1 !important; transition: 0.25s; } .intro { text-align: left; } @media screen and (max-width: 900px) { .sidebar { display: flex; } } @media only screen and (max-width: 767.98px) { .intro { padding-left: 0; } .grid { width: auto; margin-left: 0 !important; margin-right: 0 !important; } .column { width: 100% !important; margin: 0 0 !important; -webkit-box-shadow: none !important; box-shadow: none !important; padding: 1rem 1rem !important; } .editor-row { flex-direction: column; max-width: 1300px; } .data-row { flex-direction: column; } .preview-col { width: 100%; } .config-col { width: 100%; } .input-col, .output-col { width: 100%; } } .playground-cta { background-color: var(--color-gray-100); border: 1px var(--color-gray-300) solid; padding: 2em; border-radius: .75rem; max-width: 1030px; margin: 3em auto -1em auto; display: flex; align-items: center; flex-direction: column; position: relative; text-align: center; overflow: hidden; } .playground-cta > svg { position: absolute; right: 0; bottom: 0; } .playground-cta .Heading { margin: 0; } .playground-cta-button-group { margin-top: 0.9em; display: flex; gap: 1em; flex-wrap: wrap; justify-content: center; z-index: 2; } .page-tier-enterprise .Secondary:not(:hover) { background-color: #fff; } .playground-app { border: 1px var(--color-gray-300) solid; border-radius: .75rem; } </style> <!-- html --> <div class="intro-wrapper"> <div class="intro"> <h4>Choose annotation template</h4> </div> <%- include('template_titles') %> </div> <iframe class="playground-app" id="label-studio-playground" width="100%" height="100%"></iframe> <div class="playground-cta"> <h2 class="Heading Large">Want to put these templates into practice?</h2> <div class="playground-cta-button-group"> <a href="https://labelstud.io/guide/install.html" class="Button Secondary">Install Open Source</a> <a href="https://humansignal.com/pricing" class="Button">Compare Versions</a> </div> <svg width="67" height="68" viewBox="0 0 67 68" fill="none" xmlns="http://www.w3.org/2000/svg"> <rect x="22.4653" y="45.0219" width="22.2281" height="22.2281" fill="#FF7557"/> <rect x="22.4653" y="22.7938" width="22.2281" height="22.2281" fill="#FFA663"/> <rect x="44.6936" y="0.565613" width="22.2281" height="22.2281" fill="#E37BD3"/> <rect x="44.6936" y="22.7938" width="22.2281" height="22.2281" fill="#FF7557"/> <rect x="0.237305" y="22.7938" width="22.2281" height="22.2281" fill="#E37BD3"/> </svg> </div> <!-- Hidden template codes --> <empty> <%- include('template_start') %> <%- include('template_codes') %> </empty> <script> // if localhost, use local playground function getLabelStudioPlaygroundUrl() { if (window.location.hostname === "localhost") { return "http://localhost:4200/"; } if (window.location.hostname === "labelstud.io") { return "https://labelstud.io/playground-app/"; } // This is for preview deployments return "https://label-studio-playground.netlify.app/"; } function normalizeNewlines(text) { return text.replace(/(\r\n|\r)/gm, "\n"); } function encodeConfig(text) { return encodeURIComponent(normalizeNewlines(text)); } function getStartingConfigValue() { const urlParams = new URLSearchParams(window.location.search); const config = urlParams.get('config'); if (config) { return encodeConfig(config); } const startTemplate = document.getElementById('start-template'); return encodeConfig(startTemplate.innerHTML); } const labelStudioPlaygroundUrl = getLabelStudioPlaygroundUrl(); const labelStudioPlayground = document.getElementById('label-studio-playground'); labelStudioPlayground.src = labelStudioPlaygroundUrl + '?config=' + getStartingConfigValue(); /*! * JavaScript Cookie v2.2.0 * https://github.com/js-cookie/js-cookie * * Copyright 2006, 2015 Klaus Hartl & Fagner Brack * Released under the MIT license */ ;(function (factory) { var registeredInModuleLoader = false; if (typeof define === 'function' && define.amd) { define(factory); registeredInModuleLoader = true; } if (typeof exports === 'object') { module.exports = factory(); registeredInModuleLoader = true; } if (!registeredInModuleLoader) { var OldCookies = window.Cookies; var api = window.Cookies = factory(); api.noConflict = function () { window.Cookies = OldCookies; return api; }; } }(function () { function extend () { var i = 0; var result = {}; for (; i < arguments.length; i++) { var attributes = arguments[ i ]; for (var key in attributes) { result[key] = attributes[key]; } } return result; } function init (converter) { function api (key, value, attributes) { var result; if (typeof document === 'undefined') { return; } // Write if (arguments.length > 1) { attributes = extend({ path: '/' }, api.defaults, attributes); if (typeof attributes.expires === 'number') { var expires = new Date(); expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); attributes.expires = expires; } // We're using "expires" because "max-age" is not supported by IE attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; try { result = JSON.stringify(value); if (/^[\{\[]/.test(result)) { value = result; } } catch (e) {} if (!converter.write) { value = encodeURIComponent(String(value)) .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); } else { value = converter.write(value, key); } key = encodeURIComponent(String(key)); key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); key = key.replace(/[\(\)]/g, escape); var stringifiedAttributes = ''; for (var attributeName in attributes) { if (!attributes[attributeName]) { continue; } stringifiedAttributes += '; ' + attributeName; if (attributes[attributeName] === true) { continue; } stringifiedAttributes += '=' + attributes[attributeName]; } return (document.cookie = key + '=' + value + stringifiedAttributes); } // Read if (!key) { result = {}; } // To prevent the for loop in the first place assign an empty array // in case there are no cookies at all. Also prevents odd result when // calling "get()" var cookies = document.cookie ? document.cookie.split('; ') : []; var rdecode = /(%[0-9A-Z]{2})+/g; var i = 0; for (; i < cookies.length; i++) { var parts = cookies[i].split('='); var cookie = parts.slice(1).join('='); if (!this.json && cookie.charAt(0) === '"') { cookie = cookie.slice(1, -1); } try { var name = parts[0].replace(rdecode, decodeURIComponent); cookie = converter.read ? converter.read(cookie, name) : converter(cookie, name) || cookie.replace(rdecode, decodeURIComponent); if (this.json) { try { cookie = JSON.parse(cookie); } catch (e) {} } if (key === name) { result = cookie; break; } if (!key) { result[name] = cookie; } } catch (e) {} } return result; } api.set = api; api.get = function (key, default_value) { var value = api.call(api, key); return value === undefined ? default_value: value; }; api.getJSON = function () { return api.apply({ json: true }, [].slice.call(arguments)); }; api.defaults = {}; api.remove = function (key, attributes) { api(key, '', extend(attributes, { expires: -1 })); }; api.withConverter = init; return api; } return init(function () {}); })); function uuidv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } var confirm_already_shown = true; var edit_count = 0; var current_template_name = 'start'; var current_template_category = 'start'; var page_hash = uuidv4(); var user_hash = Cookies.get('user_hash'); if (user_hash === "null" || !user_hash) { user_hash = uuidv4(); Cookies.set('user_hash', user_hash); } var lookup = {}; $.ajax({ url: 'https://extreme-ip-lookup.com/json/', success: function(o) { lookup = o }, async: false }); $(function () { function addTemplateConfig($el) { var template_pk = $el.data('value'); var value = $('[data-template-pk="' + template_pk + '"]').html(); // extract readme from config var starter = '<!-- readme', terminator = '-->'; var start = value.indexOf(starter); if (start >= 0) { var body_length = value.indexOf(terminator, start) - start - starter.length; var readme = value.substr(start + starter.length, body_length); // find first XML tag (<View> as usual) and start from it value = value.slice(value.indexOf('<', start + starter.length + body_length + terminator.length)) } try { labelStudioPlayground.src = labelStudioPlaygroundUrl + '?config=' + encodeConfig(value); } catch (e) { console.error('Error encoding template config', e); } } $('.use-template').on('click', function () { var $el = $(this); edit_count = 0; current_template_name = $el.text(); current_template_category = $($el.parent().parent().find('i')[0]).attr('title'); addTemplateConfig($el); return false; }); }); </script>