mirror of
https://github.com/HeyPuter/puter.git
synced 2026-08-26 07:57:10 +00:00
Gui deploy workers (#1409)
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test (18.x) (push) Has been cancelled
test / test (20.x) (push) Has been cancelled
test / test (22.x) (push) Has been cancelled
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test (18.x) (push) Has been cancelled
test / test (20.x) (push) Has been cancelled
test / test (22.x) (push) Has been cancelled
* add deploy as worker context menu item * Update UIWindowPublishWorker.js * quick fix * Update new_context_menu_item.js * Show spinner when publishing workers * Improve worker default file * fix --------- Co-authored-by: ProgrammerIn-wonderland <3838shah@gmail.com>
This commit is contained in:
co-authored by
ProgrammerIn-wonderland
parent
6578d4d91c
commit
54aaed3459
@@ -25,6 +25,7 @@ import UIPopover from './UIPopover.js';
|
||||
import UIWindowEmailConfirmationRequired from './UIWindowEmailConfirmationRequired.js';
|
||||
import UIContextMenu from './UIContextMenu.js'
|
||||
import UIAlert from './UIAlert.js'
|
||||
import UIWindowPublishWorker from './UIWindowPublishWorker.js';
|
||||
import path from "../lib/path.js"
|
||||
import truncate_filename from '../helpers/truncate_filename.js';
|
||||
import launch_app from "../helpers/launch_app.js"
|
||||
@@ -1137,6 +1138,17 @@ function UIItem(options){
|
||||
});
|
||||
|
||||
}
|
||||
//-------------------------------------------
|
||||
// Publish as Worker
|
||||
// -------------------------------------------
|
||||
if(!is_trashed && !is_trash && !options.is_dir && $(el_item).attr('data-name').toLowerCase().endsWith('.js')){
|
||||
menu_items.push({
|
||||
html: i18n('publish_as_serverless_worker'),
|
||||
onClick: async function(){
|
||||
UIWindowPublishWorker(options.uid, $(el_item).attr('data-name'), $(el_item).attr('data-path'));
|
||||
}
|
||||
});
|
||||
}
|
||||
// -------------------------------------------
|
||||
// Deploy As App
|
||||
// -------------------------------------------
|
||||
@@ -1158,7 +1170,6 @@ function UIItem(options){
|
||||
|
||||
menu_items.push('-');
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
// Empty Trash
|
||||
// -------------------------------------------
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Copyright (C) 2024-present Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter.
|
||||
*
|
||||
* Puter is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import UIWindow from './UIWindow.js'
|
||||
import UIWindowMyWebsites from './UIWindowMyWebsites.js'
|
||||
|
||||
async function UIWindowPublishWorker(target_dir_uid, target_dir_name, target_dir_path){
|
||||
let h = '';
|
||||
h += `<div class="window-publishWorker-content" style="padding: 20px; border-bottom: 1px solid #ced7e1;">`;
|
||||
// success
|
||||
h += `<div class="window-publishWorker-success">`;
|
||||
h += `<img src="${html_encode(window.icons['c-check.svg'])}" style="width:80px; height:80px; display: block; margin:10px auto;">`;
|
||||
h += `<p style="text-align:center;">${i18n('dir_published_as_website', `<strong>${html_encode(target_dir_name)}</strong>`, false)}<p>`;
|
||||
h += `<p style="text-align:center;"><a class="publishWorker-published-link" target="_blank"></a><img class="publishWorker-published-link-icon" src="${html_encode(window.icons['launch.svg'])}"></p>`;
|
||||
h += `<button class="button button-normal button-block button-primary publish-window-ok-btn" style="margin-top:20px;">${i18n('ok')}</button>`;
|
||||
h+= `</div>`;
|
||||
// form
|
||||
h += `<form class="window-publishWorker-form">`;
|
||||
// error msg
|
||||
h += `<div class="publish-worker-error-msg"></div>`;
|
||||
// worker name
|
||||
h += `<div style="overflow: hidden;">`;
|
||||
h += `<label style="margin-bottom: 10px;">${i18n('pick_name_for_worker')}</label>`;
|
||||
h += `<div style="font-family: monospace;">${html_encode(window.extractProtocol(window.url))}://<input class="publish-worker-name" style="width:235px;" type="text" autocomplete="subdomain" spellcheck="false" autocorrect="off" autocapitalize="off" data-gramm_editor="false"/>${html_encode('.puter.work')}</div>`;
|
||||
h += `</div>`;
|
||||
// uid
|
||||
h += `<input class="publishWebsiteTargetDirUID" type="hidden" value="${html_encode(target_dir_uid)}"/>`;
|
||||
// Publish
|
||||
h += `<button class="publish-btn button button-action button-block button-normal">${i18n('publish')}</button>`
|
||||
h += `</form>`;
|
||||
h += `</div>`;
|
||||
|
||||
const el_window = await UIWindow({
|
||||
title: i18n('window_title_publish_worker'),
|
||||
icon: null,
|
||||
uid: null,
|
||||
is_dir: false,
|
||||
body_content: h,
|
||||
has_head: true,
|
||||
selectable_body: false,
|
||||
draggable_body: false,
|
||||
allow_context_menu: false,
|
||||
is_resizable: false,
|
||||
is_droppable: false,
|
||||
init_center: true,
|
||||
allow_native_ctxmenu: true,
|
||||
allow_user_select: true,
|
||||
width: 450,
|
||||
dominant: true,
|
||||
onAppend: function(this_window){
|
||||
$(this_window).find(`.publish-worker-name`).val(window.generate_identifier());
|
||||
$(this_window).find(`.publish-worker-name`).get(0).focus({preventScroll:true});
|
||||
},
|
||||
window_class: 'window-publishWorker',
|
||||
window_css:{
|
||||
height: 'initial'
|
||||
},
|
||||
body_css: {
|
||||
width: 'initial',
|
||||
height: '100%',
|
||||
'background-color': 'rgb(245 247 249)',
|
||||
'backdrop-filter': 'blur(3px)',
|
||||
}
|
||||
})
|
||||
|
||||
$(el_window).find('.publish-btn').on('click', function(e){
|
||||
// todo do some basic validation client-side
|
||||
|
||||
//Worker name
|
||||
let worker_name = $(el_window).find('.publish-worker-name').val();
|
||||
|
||||
// Store original text and replace with spinner
|
||||
const originalText = $(el_window).find('.publish-btn').text();
|
||||
$(el_window).find('.publish-btn').prop('disabled', true).html(`
|
||||
<div style="display: inline-block; margin-top: 10px; width: 16px; height: 16px; border: 2px solid #ffffff; border-radius: 50%; border-top: 2px solid transparent; animation: spin 1s linear infinite;"></div>
|
||||
`);
|
||||
|
||||
puter.workers.create(
|
||||
worker_name,
|
||||
target_dir_path).then((res)=>{
|
||||
let url = 'https://' + worker_name + '.puter.work';
|
||||
$(el_window).find('.window-publishWorker-form').hide(100, function(){
|
||||
$(el_window).find('.publishWorker-published-link').attr('href', url);
|
||||
$(el_window).find('.publishWorker-published-link').text(url);
|
||||
$(el_window).find('.window-publishWorker-success').show(100)
|
||||
$(`.item[data-uid="${target_dir_uid}"] .item-has-website-badge`).show();
|
||||
});
|
||||
|
||||
// find all items whose path starts with target_dir_path
|
||||
$(`.item[data-path^="${target_dir_path}/"]`).each(function(){
|
||||
// show the link badge
|
||||
$(this).find('.item-has-website-url-badge').show();
|
||||
// update item's website_url attribute
|
||||
$(this).attr('data-website_url', url + $(this).attr('data-path').substring(target_dir_path.length));
|
||||
})
|
||||
}).catch((err)=>{
|
||||
err = err.error;
|
||||
$(el_window).find('.publish-worker-error-msg').html(
|
||||
err.message + (
|
||||
err.code === 'subdomain_limit_reached' ?
|
||||
' <span class="manage-your-websites-link">' + i18n('manage_your_subdomains') + '</span>' : ''
|
||||
)
|
||||
);
|
||||
$(el_window).find('.publish-worker-error-msg').fadeIn();
|
||||
// re-enable 'Publish' button and restore original text
|
||||
$(el_window).find('.publish-btn').prop('disabled', false).text(originalText);
|
||||
})
|
||||
})
|
||||
|
||||
$(el_window).find('.publish-window-ok-btn').on('click', function(){
|
||||
$(el_window).close();
|
||||
})
|
||||
}
|
||||
|
||||
$(document).on('click', '.manage-your-websites-link', async function(e){
|
||||
UIWindowMyWebsites();
|
||||
})
|
||||
|
||||
|
||||
export default UIWindowPublishWorker
|
||||
@@ -1900,7 +1900,7 @@ label {
|
||||
}
|
||||
/***************************************************/
|
||||
|
||||
.login-error-msg, .signup-error-msg, .publish-website-error-msg, .form-error-msg {
|
||||
.login-error-msg, .signup-error-msg, .publish-website-error-msg, .form-error-msg, .publish-worker-error-msg {
|
||||
display: none;
|
||||
color: red;
|
||||
border: 1px solid red;
|
||||
@@ -1937,7 +1937,7 @@ label {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.window-publishWebsite-success, .window-give-item-access-success {
|
||||
.window-publishWebsite-success, .window-give-item-access-success, .window-publishWorker-success {
|
||||
display: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
@@ -1950,16 +1950,16 @@ label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.publishWebsite-published-link {
|
||||
.publishWebsite-published-link, .publishWorker-published-link {
|
||||
text-decoration: none;
|
||||
color: #007cff;
|
||||
}
|
||||
|
||||
.publishWebsite-published-link:hover {
|
||||
.publishWebsite-published-link:hover, .publishWorker-published-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.publishWebsite-published-link-icon {
|
||||
.publishWebsite-published-link-icon, .publishWorker-published-link-icon {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
margin-left: 5px;
|
||||
|
||||
@@ -155,6 +155,30 @@ const new_context_menu_item = function(dirname, append_to_element){
|
||||
});
|
||||
}
|
||||
},
|
||||
// Worker
|
||||
{
|
||||
html: i18n('worker'),
|
||||
icon: `<img src="${html_encode(window.icons['file-js.svg'])}" class="ctx-item-icon">`,
|
||||
onClick: async function() {
|
||||
await window.create_file({
|
||||
dirname: dirname,
|
||||
append_to_element: append_to_element,
|
||||
name: 'New Worker.js',
|
||||
content: `// This is an example application for Puter Workers
|
||||
|
||||
router.get('/', ({request}) => {
|
||||
return 'Hello World'; // returns a string
|
||||
});
|
||||
router.get('/api/hello', ({request}) => {
|
||||
return {'msg': 'hello'}; // returns a JSON object
|
||||
});
|
||||
router.get('/*page', ({request, params}) => {
|
||||
return new Response(\`Page \${params.page} not found\`, {status: 404});
|
||||
});
|
||||
`
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
//Show file_templates on the lower part of "New"
|
||||
|
||||
@@ -211,6 +211,7 @@ const en = {
|
||||
path: 'Path',
|
||||
personalization: "Personalization",
|
||||
pick_name_for_website: "Pick a name for your website:",
|
||||
pick_name_for_worker: "Pick a name for your worker:",
|
||||
picture: "Picture",
|
||||
pictures: 'Pictures',
|
||||
plural_suffix: 's',
|
||||
@@ -230,6 +231,7 @@ const en = {
|
||||
public: 'Public',
|
||||
publish: "Publish",
|
||||
publish_as_website: 'Publish as website',
|
||||
publish_as_serverless_worker: 'Publish as Worker',
|
||||
puter_description: `Puter is a privacy-first personal cloud to keep all your files, apps, and games in one secure place, accessible from anywhere at any time.`,
|
||||
reading: "Reading %strong%",
|
||||
writing: "Writing %strong%",
|
||||
@@ -331,6 +333,7 @@ const en = {
|
||||
you_have_been_referred_to_puter_by_a_friend: "You have been referred to Puter by a friend!",
|
||||
zip: "Zip",
|
||||
sequencing: "Sequencing %strong%",
|
||||
worker: "Worker",
|
||||
zipping: "Zipping %strong%",
|
||||
|
||||
// === 2FA Setup ===
|
||||
@@ -461,6 +464,7 @@ const en = {
|
||||
'window_title_set_new_password': 'Set New Password',
|
||||
'window_title_instant_login': 'Instant Login!',
|
||||
'window_title_publish_website': 'Publish Website',
|
||||
'window_title_publish_worker': 'Publish Worker',
|
||||
'window_title_authenticating': 'Authenticating...',
|
||||
'window_title_refer_friend': 'Refer a friend!',
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ export class WorkersHandler {
|
||||
if (!driverCall.result.result) {
|
||||
new Error("Worker doesn't exist");
|
||||
}
|
||||
throw driverCall.error || new Error(driverResult?.errors || "Driver failed to execute, do you have the necessary permissions?");
|
||||
throw driverCall.error || new Error(driverCall.result?.errors || "Driver failed to execute, do you have the necessary permissions?");
|
||||
} else {
|
||||
let currentWorkers = await puter.kv.get("user-workers");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user