diff --git a/.github/workflows/github-release.yml b/.github/workflows/github-release.yml index cfb12cb42d..01775a2eba 100644 --- a/.github/workflows/github-release.yml +++ b/.github/workflows/github-release.yml @@ -168,6 +168,7 @@ jobs: - name: Build run: | + echo 'export const VERSION = "${{ needs.prelude.outputs.tag }}"' > src/version.js ./build.sh ls -l dist diff --git a/.github/workflows/test-build-docker-image.yml b/.github/workflows/test-build-docker-image.yml index 0215e83ad3..af7a039b6f 100644 --- a/.github/workflows/test-build-docker-image.yml +++ b/.github/workflows/test-build-docker-image.yml @@ -254,6 +254,7 @@ jobs: - name: Build run: | + echo 'export const VERSION = "${{ steps.vars.outputs.version }}"' > src/version.js ./build.sh ls -l dist diff --git a/app/client/src/components/ads/Toast.tsx b/app/client/src/components/ads/Toast.tsx index 064c37ab9d..6207ec7f07 100644 --- a/app/client/src/components/ads/Toast.tsx +++ b/app/client/src/components/ads/Toast.tsx @@ -128,6 +128,7 @@ const StyledDebugButton = styled(DebugButton)` const StyledActionText = styled(Text)` color: ${(props) => props.theme.colors.toast.undoRedoColor} !important; + cursor: pointer; `; export function ToastComponent( diff --git a/app/client/src/constants/messages.ts b/app/client/src/constants/messages.ts index b134be4fe9..c219be2925 100644 --- a/app/client/src/constants/messages.ts +++ b/app/client/src/constants/messages.ts @@ -804,6 +804,8 @@ export const RESTART_BANNER_HEADER = () => "Restarting Server"; export const RESTART_ERROR_BODY = () => "Something went wrong. Please contact your administrator."; export const RESTART_ERROR_HEADER = () => "Restart failed"; +export const INFO_VERSION_MISMATCH_FOUND_RELOAD_REQUEST = () => + "Hey! There is a new version of Appsmith available. Please consider refreshing your window."; export const WELCOME_FORM_NON_SUPER_USER_ROLE_DROPDOWN = () => "Tell us more about what you do at work?"; diff --git a/app/client/src/sagas/WebsocketSagas/handleAppLevelSocketEvents.ts b/app/client/src/sagas/WebsocketSagas/handleAppLevelSocketEvents.tsx similarity index 76% rename from app/client/src/sagas/WebsocketSagas/handleAppLevelSocketEvents.ts rename to app/client/src/sagas/WebsocketSagas/handleAppLevelSocketEvents.tsx index be22d874f5..fecf1d291a 100644 --- a/app/client/src/sagas/WebsocketSagas/handleAppLevelSocketEvents.ts +++ b/app/client/src/sagas/WebsocketSagas/handleAppLevelSocketEvents.tsx @@ -12,6 +12,14 @@ import { import { collabSetAppEditors } from "actions/appCollabActions"; import { newNotificationEvent } from "actions/notificationActions"; import { getCurrentUser } from "selectors/usersSelectors"; +import { Toaster } from "components/ads/Toast"; +import { + createMessage, + INFO_VERSION_MISMATCH_FOUND_RELOAD_REQUEST, +} from "constants/messages"; +import { Variant } from "components/ads/common"; +import React from "react"; +import { getAppsmithConfigs } from "../../configs"; export default function* handleAppLevelSocketEvents(event: any) { const currentUser = yield select(getCurrentUser); @@ -75,5 +83,20 @@ export default function* handleAppLevelSocketEvents(event: any) { yield put(collabSetAppEditors(event.payload[0])); return; } + // notification on release version + case APP_LEVEL_SOCKET_EVENTS.RELEASE_VERSION_NOTIFICATION: { + const { appVersion } = getAppsmithConfigs(); + if (appVersion.id != event.payload[0]) { + Toaster.show({ + text: createMessage(INFO_VERSION_MISMATCH_FOUND_RELOAD_REQUEST), + variant: Variant.info, + actionElement: ( + location.reload(true)}>REFRESH + ), + autoClose: false, + }); + } + return; + } } } diff --git a/app/client/src/sagas/WebsocketSagas/socketEvents.ts b/app/client/src/sagas/WebsocketSagas/socketEvents.ts index cdc892c16c..642afe1c09 100644 --- a/app/client/src/sagas/WebsocketSagas/socketEvents.ts +++ b/app/client/src/sagas/WebsocketSagas/socketEvents.ts @@ -18,6 +18,8 @@ export const APP_LEVEL_SOCKET_EVENTS = { INSERT_NOTIFICATION: "insert:notification", LIST_ONLINE_APP_EDITORS: "collab:online_editors", // user presence + + RELEASE_VERSION_NOTIFICATION: "info:release_version", // release version }; export const PAGE_LEVEL_SOCKET_EVENTS = { diff --git a/app/rts/src/server.ts b/app/rts/src/server.ts index dfa818cb02..e92bb94ef6 100644 --- a/app/rts/src/server.ts +++ b/app/rts/src/server.ts @@ -7,7 +7,9 @@ import type mongodb from "mongodb" import axios from "axios" import { LogLevelDesc } from "loglevel"; import log from "loglevel"; + import { AppUser, CurrentEditorsEvent, Policy, Comment, CommentThread, MousePointerEvent } from "./models" +import { VERSION as buildVersion } from "./version" // release version of the api const RTS_BASE_PATH = "/rts" @@ -20,6 +22,7 @@ const EDITORS_EVENT_NAME : string = "collab:online_editors" const START_EDIT_EVENT_NAME : string = "collab:start_edit" const LEAVE_EDIT_EVENT_NAME : string = "collab:leave_edit" const MOUSE_POINTER_EVENT_NAME : string = "collab:mouse_pointer" +const RELEASE_VERSION_EVENT_NAME : string = "info:release_version" // Setting the logLevel for all log messages const logLevel : LogLevelDesc = (process.env.APPSMITH_LOG_LEVEL || "debug") as LogLevelDesc @@ -59,6 +62,7 @@ function main() { }) io.on("connection", (socket: Socket) => { + socket.emit(RELEASE_VERSION_EVENT_NAME, buildVersion) subscribeToEditEvents(socket, APP_ROOM_PREFIX) onAppSocketConnected(socket) .catch((error) => log.error("Error in socket connected handler", error)) @@ -71,39 +75,46 @@ function main() { }); io.of(ROOT_NAMESPACE).adapter.on("leave-room", (room, id) => { - log.debug(`ns:${ROOT_NAMESPACE}# socket ${id} left the room ${room}`) + if(room.startsWith(APP_ROOM_PREFIX)) { + log.debug(`ns:${ROOT_NAMESPACE}# socket ${id} left the room ${room}`) + } sendCurrentUsers(io, room, APP_ROOM_PREFIX); }); io.of(ROOT_NAMESPACE).adapter.on("join-room", (room, id) => { - log.debug(`ns:${ROOT_NAMESPACE}# socket ${id} joined the room ${room}`) + if(room.startsWith(APP_ROOM_PREFIX)) { + log.debug(`ns:${ROOT_NAMESPACE}# socket ${id} joined the room ${room}`) + } sendCurrentUsers(io, room, APP_ROOM_PREFIX); }); io.of(PAGE_EDIT_NAMESPACE).adapter.on("leave-room", (room, id) => { - log.debug(`ns:${PAGE_EDIT_NAMESPACE}# socket ${id} left the room ${room}`) if(room.startsWith(PAGE_ROOM_PREFIX)) { // someone left the page edit, notify others + log.debug(`ns:${PAGE_EDIT_NAMESPACE} # socket ${id} left the room ${room}`) io.of(PAGE_EDIT_NAMESPACE).to(room).emit(LEAVE_EDIT_EVENT_NAME, id); } sendCurrentUsers(io.of(PAGE_EDIT_NAMESPACE), room, PAGE_ROOM_PREFIX); }); io.of(PAGE_EDIT_NAMESPACE).adapter.on("join-room", (room, id) => { - log.debug(`ns:${PAGE_EDIT_NAMESPACE}# socket ${id} joined the room ${room}`) + if(room.startsWith(PAGE_ROOM_PREFIX)) { + log.debug(`ns:${PAGE_EDIT_NAMESPACE}# socket ${id} joined the room ${room}`) + } sendCurrentUsers(io.of(PAGE_EDIT_NAMESPACE), room, PAGE_ROOM_PREFIX); }); - watchMongoDB(io) - .catch((error) => log.error("Error watching MongoDB", error)) - app.use(express.static(path.join(__dirname, "static"))) + + watchMongoDB(io).catch((error) => log.error("Error watching MongoDB", error)) + + // run the server server.listen(port, () => { - log.info(`RTS running at http://localhost:${port}`) + log.info(`RTS version ${buildVersion} running at http://localhost:${port}`) }) } function joinEditRoom(socket:Socket, roomId:string, roomPrefix:string) { - // remove this socket from any other app rooms + // remove this socket from any other rooms with roomPrefix if(socket.rooms) { socket.rooms.forEach(roomName => { if(roomName.startsWith(roomPrefix)) { diff --git a/app/rts/src/version.js b/app/rts/src/version.js new file mode 100644 index 0000000000..5e0780e974 --- /dev/null +++ b/app/rts/src/version.js @@ -0,0 +1 @@ +export const VERSION = 'SNAPSHOT' diff --git a/app/rts/tsconfig.json b/app/rts/tsconfig.json index 3b5844c03d..7f8cefa21c 100644 --- a/app/rts/tsconfig.json +++ b/app/rts/tsconfig.json @@ -5,7 +5,8 @@ "esModuleInterop": true, "moduleResolution": "node", "sourceMap": true, - "outDir": "dist" + "outDir": "dist", + "allowJs": true }, "lib": ["es2015"] }