diff --git a/src/assets/styles/components/_web-ide.scss b/src/assets/styles/components/_web-ide.scss index 5fd2b2148..6d8148dd0 100644 --- a/src/assets/styles/components/_web-ide.scss +++ b/src/assets/styles/components/_web-ide.scss @@ -5,7 +5,7 @@ } } - color: white; + color: $color-white; .editor.current-file-path { border-bottom: 1px solid transparent; @@ -13,7 +13,7 @@ .default-window-option { span { - color: white; + color: $color-white; } } @@ -50,7 +50,7 @@ } .file-browser button > span { - color: white !important; + color: $color-white !important; } .file-browser .file.file-selected > span { @@ -74,23 +74,25 @@ .default-window-option span { - color: white !important; + color: $color-white !important; } .editor-window .default-window .default-window-container { background: $color-pureblack !important; - color: white; + color: $color-white; } .no-projects { - color: white; + color: $color-white; .docs-link { color: #ee81ee !important; } } - color: white; + color: $color-white; + + color: rgb(105, 105, 105); color: rgb(105, 105, 105); @@ -128,11 +130,11 @@ } .editor-window .cancel-button:hover { - color: white; + color: $color-white; } .package-install-window { - background: white; + background: $color-white; } .editor.current-file-path { @@ -177,6 +179,7 @@ border-bottom: 1px solid darkgray !important; } + .revert-file[disabled], .save-code[disabled] { color: #c2c2c2 !important; } @@ -228,7 +231,7 @@ color: rgb(105, 105, 105); .package-install-window { - background: white; + background: $color-white; } .editor.current-file-path { @@ -265,7 +268,7 @@ } .editor-window button:hover { - color: white; + color: $color-white; //rgb(105,105,105); } @@ -352,7 +355,7 @@ .add-file-icon { background: transparent; border: none; - color: white; + color: $color-white; margin: 0; outline: none !important; padding: 0; @@ -371,7 +374,7 @@ padding: 20px; .file-menu { - color: white; + color: $color-white; display: flex; flex-direction: row; @@ -502,7 +505,7 @@ .editor-menu { align-items: baseline; border-bottom: 1px solid #2e2e2e; - color: white; + color: $color-white; display: flex; flex-direction: row; justify-content: left; @@ -536,6 +539,7 @@ } } + .revert-file, .save-code { background: transparent; border: none; @@ -546,6 +550,7 @@ padding: 0; } + .revert-file[disabled], .save-code[disabled] { color: #5e5e5e; cursor: default; @@ -828,11 +833,11 @@ width: 40px; i { - color: white; + color: $color-white; &.not-searching { - color: white; //rgba(0,255,0, 0.1); + color: $color-white; //rgba(0,255,0, 0.1); } diff --git a/src/components/instance/functions/manage/index.js b/src/components/instance/functions/manage/index.js index 00d394856..f36c4b0d8 100644 --- a/src/components/instance/functions/manage/index.js +++ b/src/components/instance/functions/manage/index.js @@ -14,6 +14,7 @@ import deployComponent from '../../../../functions/api/instance/deployComponent' import restartService from '../../../../functions/api/instance/restartService'; import useInstanceAuth from '../../../../functions/state/instanceAuths'; +import useEditorCache from '../../../../functions/state/editorCache'; import ApplicationsEditor from '../../../shared/webide'; import CustomFunctionsEditor from './CustomFunctionsEditor'; @@ -45,19 +46,19 @@ function getDeployTargets(instanceList, instanceAuthList, thisCsId, auth) { return memo; } - const [ major, minor ] = deployTarget?.version.split('.') || []; + const [ major, minor ] = deployTarget?.version.split('.') || []; // exclude < 4.2 if (parseInt(major, 10) >= 4 && parseInt(minor, 10) >= 2) { - memo.push({ + memo.push({ isCurrentInstance: csId === thisCsId, auth, instance }); - } + } return memo; @@ -69,17 +70,44 @@ function ManageIndex({ refreshCustomFunctions, loading }) { const { compute_stack_id } = useParams(); const registration = useStoreState(instanceState, (s) => s.registration); - const { fileTree } = useStoreState(instanceState, (s) => s.custom_functions); + const { fileTree } = useStoreState(instanceState, (s) => s.custom_functions); const auth = useStoreState(instanceState, (s) => s.auth); const url = useStoreState(instanceState, (s) => s.url); const [majorVersion, minorVersion] = (registration?.version || '').split('.') || []; const supportsApplicationsAPI = parseFloat(`${majorVersion}.${minorVersion}`) >= 4.2; const instances = useStoreState(appState, (s) => s.instances); - const [instanceAuths] = useInstanceAuth({}); + const [ instanceAuths ] = useInstanceAuth({}); + const [ editorCache, setEditorCache ] = useEditorCache({}); const theme = useStoreState(appState, (s) => s.theme); const [ restartingInstance, setRestartingInstance ] = useState(false); const alert = useAlert(); + function removeFileFromLocalStorage({ path }) { + + const updatedCache = {...editorCache}; + const fileKey = `${compute_stack_id}_${path}`; + + if (fileKey in updatedCache) { + delete updatedCache[fileKey]; + } + + setEditorCache({ + ...updatedCache + }); + } + + async function saveFileToLocalStorage(selectedFile) { + const { path, content } = selectedFile; + + const fileKey = `${compute_stack_id}_${path}`; + + setEditorCache({ + ...editorCache, + [fileKey]: content + }); + + } + async function restartWithLoadingState({ auth: instanceAuth, url: instanceUrl }) { setRestartingInstance(true); @@ -96,9 +124,14 @@ function ManageIndex({ refreshCustomFunctions, loading }) { } // save file to instance - async function saveCodeToInstance(selectedFile, restartRequired) { - - const filepathRelativeToProjectDir = selectedFile.path.split('/').slice(2).join('/'); + async function saveFileToInstance(selectedFile, restartRequired) { + + // handle cached situation + // - NOTE: this 'selectedFile' is not reactive. + // - remove cache entry for this file + // - update selectedFile with new content + // - set selectedFile.cached = false. + const filepathRelativeToProjectDir = selectedFile.path.split('/').slice(2).join('/'); const payload = { auth, url, @@ -113,11 +146,13 @@ function ManageIndex({ refreshCustomFunctions, loading }) { alert.error(message); } - if (restartRequired) { await restartWithLoadingState({ auth, url }); } + removeFileFromLocalStorage({ path: selectedFile.path }); + selectedFile.cached = false; + await refreshCustomFunctions(); } @@ -156,7 +191,25 @@ function ManageIndex({ refreshCustomFunctions, loading }) { const { path, project, name } = selectedFile; const newFile = getRelativeFilepath(path); - const { error, message } = await getComponentFile({ + const fileCacheKey = `${compute_stack_id}_${path}`; + const cachedFile = editorCache[fileCacheKey]; + const isCached = fileCacheKey in editorCache; + + if (isCached) { + + return { + cached: isCached, + content: cachedFile, + path, + project, + name + }; + + } + + // TODO: set file content to local storage copy if it exists. + // + const { error, message: content } = await getComponentFile({ auth, url, project, @@ -165,19 +218,21 @@ function ManageIndex({ refreshCustomFunctions, loading }) { if (error) { - alert.error(message); + alert.error(content); return { content: '', path, project, - name + name, + cached: false }; } return { - content: message, + cached: isCached, + content, path, project, name @@ -423,14 +478,42 @@ function ManageIndex({ refreshCustomFunctions, loading }) { } + async function revertFileChanges(selectedFile) { + + // ditch local storage version + removeFileFromLocalStorage({ path: selectedFile.path }); + + // get file + // + const { error, message} = await getComponentFile({ + auth, + url, + project: selectedFile.project, + file: getRelativeFilepath(selectedFile.path) + }); + + removeFileFromLocalStorage({ path: selectedFile.path }); + + if (error) { + return alert.error(message); + } + + await refreshCustomFunctions(); + + return message; + + } + return supportsApplicationsAPI ?
- - {filepathRelativeToComponentsDir} + path: {filepathRelativeToComponentsDir} + size: {file.size} bytes + last saved: {file.mtime}
{ setLoading(true); - await onSave(); + await onClick(); setTimeout(() => { setLoading(false); }, 500); @@ -50,10 +50,10 @@ export function RestartInstanceButton({ onClick, restarting }) { ); } -export function RestartOnSaveToggle({ restartAfterSave, onClick }) { +export function RestartOnSaveToggle({ onClick, restartAfterSave }) { const title = restartAfterSave ? - 'your instance will restart after saving application files' : + 'restart instance after saving application files' : 'your instance will not restart after saving application files'; return ( @@ -74,7 +74,22 @@ export function RestartOnSaveToggle({ restartAfterSave, onClick }) { ); } -export default function EditorMenu({ SaveButton: SaveBtn, RestartInstanceButton: RestartInstanceBtn, RestartOnSaveToggle: RestartOnSaveTgl }) { +export function RevertFileButton({ onClick, disabled }) { + return ( +