* [PATCH v1 01/13] refactor: migrate: migrate to sveltekit framework
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 02/13] feat(app): add app types file Muhammad Rizki
` (11 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This commit involves migrating the project to the SvelteKit framework,
replacing the previous use of Vanilla JS.
New files have been added to support the migration:
- src/ (Main app source)
- routes/ (Page routing)
- +layout.svelte (Layout UI)
- app.css (Main app CSS styles)
- app.d.ts (App types)
- app.html (Root app web page HTML)
- .eslintignore (ESLint ignore file)
- .eslintrc.cjs (ESLint configuration file)
- .prettierignore (Prettier ignore file for specific files)
- .prettierrc (Prettier configuration file for code formatting)
- svelte.config.js (SvelteKit config file)
- tsconfig.json (TypeScript compiler options configuration file)
- vite.config.ts (Vite configuration file)
Note that these new files were generated based on the recommendation
from the NPM command `npm create svelte@latest`. Although it initially
includes `routes/+page.svelte`, we've chosen not to include it for now,
as we plan to modify `routes/+page.svelte` later in the project.
Additionally, several existing files related to the project structure
have been modified:
- .gitignore
- package.json
- postcss.config.js
- tailwind.config.js
These modifications were necessary, particularly in the
`postcss.config.js` and `tailwind.config.js` files, as they now adhere
to the `"module"` project type and have been updated from
`module.exports` to `export default`. Furthermore,
the `tailwind.config.js` file has been modified to include class name
detection for `"./src/**/*.{html,js,svelte,ts}"` files.
Signed-off-by: Muhammad Rizki <[email protected]>
---
.eslintignore | 13 +++++++++
.eslintrc.cjs | 30 ++++++++++++++++++++
.gitignore | 6 ++++
.prettierignore | 13 +++++++++
.prettierrc | 9 ++++++
package.json | 41 +++++++++++++++++----------
postcss.config.js | 2 +-
src/app.css | 3 ++
src/app.d.ts | 12 ++++++++
src/app.html | 11 ++++++++
src/routes/+layout.svelte | 58 +++++++++++++++++++++++++++++++++++++++
svelte.config.js | 23 ++++++++++++++++
tailwind.config.js | 8 +++---
tsconfig.json | 13 +++++++++
vite.config.ts | 6 ++++
15 files changed, 228 insertions(+), 20 deletions(-)
create mode 100644 .eslintignore
create mode 100644 .eslintrc.cjs
create mode 100644 .prettierignore
create mode 100644 .prettierrc
create mode 100644 src/app.css
create mode 100644 src/app.d.ts
create mode 100644 src/app.html
create mode 100644 src/routes/+layout.svelte
create mode 100644 svelte.config.js
create mode 100644 tsconfig.json
create mode 100644 vite.config.ts
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..3897265
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..fc897e0
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,30 @@
+module.exports = {
+ root: true,
+ extends: [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:svelte/recommended",
+ "prettier"
+ ],
+ parser: "@typescript-eslint/parser",
+ plugins: ["@typescript-eslint"],
+ parserOptions: {
+ sourceType: "module",
+ ecmaVersion: 2020,
+ extraFileExtensions: [".svelte"]
+ },
+ env: {
+ browser: true,
+ es2017: true,
+ node: true
+ },
+ overrides: [
+ {
+ files: ["*.svelte"],
+ parser: "svelte-eslint-parser",
+ parserOptions: {
+ parser: "@typescript-eslint/parser"
+ }
+ }
+ ]
+};
diff --git a/.gitignore b/.gitignore
index 0c55e77..7ccdc00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,12 @@
dist
+.DS_Store
node_modules
+/build
+/.svelte-kit
+/package
.env
.vscode
pnpm-lock.yaml
package-lock.json
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..3897265
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..c04a571
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,9 @@
+{
+ "semi": true,
+ "singleQuote": false,
+ "trailingComma": "none",
+ "printWidth": 100,
+ "plugins": ["prettier-plugin-svelte"],
+ "pluginSearchDirs": ["."],
+ "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
+}
diff --git a/package.json b/package.json
index 002cdbe..6ea9985 100644
--- a/package.json
+++ b/package.json
@@ -2,23 +2,34 @@
"name": "gnuweeb-org-web",
"version": "1.0.0",
"description": "gnuweeb.org website",
+ "type": "module",
"scripts": {
- "watch": "tailwindcss -i ./style.css -o ./dist/style.css --watch && npm run build:static && npm run build:html",
- "serve": "serve",
- "dev": "concurrently \"npm run watch\" \"npm run serve\"",
- "build:css": "tailwindcss -i ./style.css -o ./dist/style.css --minify && postcss ./dist/style.css -o ./dist/style.css --use autoprefixer --no-map",
- "build:static": "cp -r ./static ./dist",
- "build:html": "cat ./index.html | sed 's/dist/./' > ./dist/index.html",
- "build:minify": "node build.js",
- "build": "npm run build:css && npm run build:static && npm run build:html && npm run build:minify"
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "vite preview",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "lint": "prettier --plugin-search-dir . --check . && eslint .",
+ "format": "prettier --plugin-search-dir . --write ."
},
"devDependencies": {
- "autoprefixer": "^10.4.15",
- "concurrently": "^8.2.0",
- "html-minifier-terser": "^7.2.0",
- "postcss": "^8.4.28",
- "postcss-cli": "^10.1.0",
- "serve": "^14.2.0",
- "tailwindcss": "^3.3.3"
+ "@sveltejs/adapter-auto": "^2.0.0",
+ "@sveltejs/adapter-node": "^1.3.1",
+ "@sveltejs/kit": "^1.20.4",
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
+ "@typescript-eslint/parser": "^6.0.0",
+ "autoprefixer": "^10.4.16",
+ "eslint": "^8.28.0",
+ "eslint-config-prettier": "^8.5.0",
+ "eslint-plugin-svelte": "^2.30.0",
+ "postcss": "^8.4.31",
+ "prettier": "^2.8.0",
+ "prettier-plugin-svelte": "^2.10.1",
+ "svelte": "^4.0.5",
+ "svelte-check": "^3.4.3",
+ "tailwindcss": "^3.3.3",
+ "tslib": "^2.4.1",
+ "typescript": "^5.0.0",
+ "vite": "^4.4.2"
}
}
diff --git a/postcss.config.js b/postcss.config.js
index 12a703d..2aa7205 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -1,4 +1,4 @@
-module.exports = {
+export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
diff --git a/src/app.css b/src/app.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/src/app.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/src/app.d.ts b/src/app.d.ts
new file mode 100644
index 0000000..f59b884
--- /dev/null
+++ b/src/app.d.ts
@@ -0,0 +1,12 @@
+// See https://kit.svelte.dev/docs/types#app
+// for information about these interfaces
+declare global {
+ namespace App {
+ // interface Error {}
+ // interface Locals {}
+ // interface PageData {}
+ // interface Platform {}
+ }
+}
+
+export {};
diff --git a/src/app.html b/src/app.html
new file mode 100644
index 0000000..9324995
--- /dev/null
+++ b/src/app.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width" />
+ %sveltekit.head%
+ </head>
+ <body data-sveltekit-preload-data="hover">
+ <div style="display: contents">%sveltekit.body%</div>
+ </body>
+</html>
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
new file mode 100644
index 0000000..21ee482
--- /dev/null
+++ b/src/routes/+layout.svelte
@@ -0,0 +1,58 @@
+<script>
+ import "../app.css";
+</script>
+
+
+<!-- head element -->
+<svelte:head>
+ <meta http-equiv="X-UA-Compatible" content="ie=edge" />
+ <meta property="og:title" content="GNU/Weeb" />
+ <meta property="og:description" content="We are working to build community through open source technology." />
+ <meta property="og:image" content="./og-image.png" />
+ <meta property="og:url" content="https://www.gnuweeb.org/" />
+ <meta property="og:type" content="website" />
+ <meta property="og:site_name" content="GNU/Weeb" />
+ <meta name="twitter:card" content="summary_large_image" />
+ <meta name="description" content="We are working to build community through open source technology.">
+
+ <title>GNU/Weeb - Home</title>
+
+ <link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
+ <link rel="canonical" href="https://www.gnuweeb.org/" />
+ <link
+ rel="apple-touch-icon"
+ sizes="180x180"
+ href="./apple-touch-icon.png"
+ />
+ <link
+ rel="icon"
+ type="image/png"
+ sizes="32x32"
+ href="./favicon-32x32.png"
+ />
+ <link
+ rel="icon"
+ type="image/png"
+ sizes="16x16"
+ href="./favicon-16x16.png"
+ />
+ <link rel="manifest" href="./site.webmanifest" />
+</svelte:head>
+
+
+<div class="w-full px-20 bg-neutral-950 text-neutral-200">
+
+ <!-- main/root element -->
+ <main class="flex justify-center w-full min-h-screen">
+ <!-- slot will contains all contents from all the others +page.svelte inside routes/ dir -->
+ <slot/>
+ </main>
+
+ <!-- footer element -->
+ <footer class="pt-10 p-5">
+ <p class="text-xs opacity-70 mx-auto text-center">
+ © 2023 GNU/Weeb.<br />Licensed under BSD 3-Clause License.
+ </p>
+ </footer>
+
+</div>
diff --git a/svelte.config.js b/svelte.config.js
new file mode 100644
index 0000000..18ebc16
--- /dev/null
+++ b/svelte.config.js
@@ -0,0 +1,23 @@
+import adapter from "@sveltejs/adapter-node";
+import { vitePreprocess } from "@sveltejs/kit/vite";
+
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ preprocess: vitePreprocess(),
+ kit: {
+ adapter: adapter({
+ out: "dist",
+ precompress: true,
+ envPrefix: "",
+ polyfill: true
+ }),
+ alias: {
+ $lib: "src/lib",
+ $types: "src/app.d.ts",
+ $components: "src/lib/components/"
+ }
+ }
+};
+
+export default config;
diff --git a/tailwind.config.js b/tailwind.config.js
index 39fb13d..78f2938 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,8 +1,8 @@
/** @type {import('tailwindcss').Config} */
-module.exports = {
- content: ["./*.html"],
+export default {
+ content: ["./src/**/*.{html,js,svelte,ts}"],
theme: {
- extend: {},
+ extend: {}
},
- plugins: [],
+ plugins: []
};
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..5c56cee
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true
+ }
+}
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 0000000..78e127f
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,6 @@
+import { sveltekit } from "@sveltejs/kit/vite";
+import { defineConfig } from "vite";
+
+export default defineConfig({
+ plugins: [sveltekit()]
+});
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 02/13] feat(app): add app types file
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 01/13] refactor: migrate: migrate to sveltekit framework Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 03/13] feat(lib): add API_URL and STORAGE_URL constant variable Muhammad Rizki
` (10 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This file is for storing the type interface of the app.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/app.d.ts | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/src/app.d.ts b/src/app.d.ts
index f59b884..1ef91f3 100644
--- a/src/app.d.ts
+++ b/src/app.d.ts
@@ -9,4 +9,40 @@ declare global {
}
}
-export {};
+interface GitHubOrgsAPIResponseType {
+ login: string
+ id: number
+ node_id: string
+ avatar_url: string
+ gravatar_id: string
+ url: string
+ html_url: string
+ followers_url: string
+ following_url: string
+ gists_url: string
+ starred_url: string
+ subscriptions_url: string
+ organizations_url: string
+ repos_url: string
+ events_url: string
+ received_events_url: string
+ type: string
+ site_admin: boolean
+}
+
+interface RecentMessagesReturnType {
+ user_id: number
+ username: string | null
+ first_name: string
+ last_name: string | null
+ user_photo: string | null
+ message_id: number
+ reply_to_message_id: number | null
+ message_type: string
+ text: string | null
+ text_entities: string | null
+ file: string | null
+ date: string
+}
+
+export { GitHubOrgsAPIResponseType, RecentMessagesReturnType };
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 03/13] feat(lib): add API_URL and STORAGE_URL constant variable
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 01/13] refactor: migrate: migrate to sveltekit framework Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 02/13] feat(app): add app types file Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 04/13] feat(lib): add lib functions file Muhammad Rizki
` (9 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
These variable will be used to make fetching the API URL and getting the
asset image files easier.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/lib/constants.ts | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 src/lib/constants.ts
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
new file mode 100644
index 0000000..21a5e33
--- /dev/null
+++ b/src/lib/constants.ts
@@ -0,0 +1,2 @@
+export const API_URL = "https://telegram-bot.teainside.org";
+export const STORAGE_URL = API_URL + "/storage/files/";
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 04/13] feat(lib): add lib functions file
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (2 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 03/13] feat(lib): add API_URL and STORAGE_URL constant variable Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 05/13] feat(lib): add newly created lib constants variables and functions Muhammad Rizki
` (8 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This file contains helper functions, and there are no changes from the
previous version. We've simply added some type annotations for
TypeScript support.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/lib/functions.ts | 95 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
create mode 100644 src/lib/functions.ts
diff --git a/src/lib/functions.ts b/src/lib/functions.ts
new file mode 100644
index 0000000..0357e6b
--- /dev/null
+++ b/src/lib/functions.ts
@@ -0,0 +1,95 @@
+import type { GitHubOrgsAPIResponseType, RecentMessagesReturnType } from "$types";
+import { API_URL } from "./constants";
+
+
+export const getOrgMembers = async (): Promise<GitHubOrgsAPIResponseType[]> => {
+ const response = await fetch("https://api.github.com/orgs/gnuweeb/members");
+ const data: GitHubOrgsAPIResponseType[] = await response.json();
+
+ data.sort((
+ left: GitHubOrgsAPIResponseType,
+ right: GitHubOrgsAPIResponseType
+ ) => {
+ const usernameA = left.login.toLowerCase();
+ const usernameB = right.login.toLowerCase();
+ if (usernameA < usernameB) return -1;
+ if (usernameA > usernameB) return 1;
+ return 0;
+ });
+
+ return data;
+}
+
+export const getRecentMessages = async (): Promise<RecentMessagesReturnType[] | []> => {
+ try {
+ const response = await fetch(API_URL + "/zxc.php?action=get_messages&chat_id=-1001483770714&limit=50");
+ const { data } = (await response.json()).result;
+
+ const transformedData = data.map((item: any) => {
+ return {
+ user_id: item[0],
+ username: item[1],
+ first_name: item[2],
+ last_name: item[3],
+ user_photo: item[4],
+ message_id: item[5],
+ reply_to_message_id: item[6],
+ message_type: item[7],
+ text: item[8],
+ text_entities: item[9] ? JSON.parse(item[9]) : null,
+ file: item[10],
+ date: item[11]
+ };
+ });
+
+ return transformedData.reverse();
+ } catch {
+ return [];
+ }
+}
+
+const hashCode = (name: string) => {
+ var hash = 0;
+ for (var i = 0; i < name.length; i++) {
+ var character = name.charCodeAt(i);
+ hash = ((hash << 5) - hash) + character;
+ }
+ return Math.abs(hash);
+}
+
+export const getFixedRandomColor = (name: string) => {
+ const colorData: Record<string, string> = {
+ red: "text-red-400 border-red-400",
+ yellow: "text-yellow-400 border-yellow-400",
+ blue: "text-blue-400 border-blue-400",
+ sky: "text-sky-400 border-sky-400",
+ purple: "text-purple-400 border-purple-400",
+ orange: "text-orange-400 border-orange-400",
+ amber: "text-amber-400 border-amber-400",
+ lime: "text-lime-400 border-lime-400",
+ green: "text-green-400 border-green-400",
+ emerald: "text-emerald-400 border-emerald-400",
+ teal: "text-teal-400 border-teal-400",
+ cyan: "text-cyan-400 border-cyan-400",
+ indigo: "text-indigo-400 border-indigo-400",
+ violet: "text-violet-400 border-violet-400",
+ fuchsia: "text-fuchsia-400 border-fuchsia-400",
+ pink: "text-pink-400 border-pink-400",
+ rose: "text-rose-400 border-rose-400",
+ };
+ const colorNames = Object.keys(colorData);
+ return colorData[colorNames[hashCode(name) % colorNames.length]].split(" ");
+}
+
+export const cleanMessageText = (text: string) => {
+ return text.replaceAll(/\n/g, " ");
+}
+
+export const setupUserName = (first: string, last: string | null) => {
+ const firstName = first.trimEnd();
+ let lastName = "";
+ if(last !== null) {
+ lastName = " " + last.trimEnd();
+ }
+ return [ firstName, lastName ];
+}
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 05/13] feat(lib): add newly created lib constants variables and functions
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (3 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 04/13] feat(lib): add lib functions file Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 06/13] feat(lib/functions): add getRepliedMessage() function Muhammad Rizki
` (7 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This commit includes imports and exports to `index.ts`, making it easier
to access them using `"$lib"`.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/lib/index.ts | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100644 src/lib/index.ts
diff --git a/src/lib/index.ts b/src/lib/index.ts
new file mode 100644
index 0000000..e8a9d9b
--- /dev/null
+++ b/src/lib/index.ts
@@ -0,0 +1,22 @@
+import {
+ API_URL,
+ STORAGE_URL,
+} from "./constants";
+
+import {
+ getRecentMessages,
+ getOrgMembers,
+ getFixedRandomColor,
+ cleanMessageText,
+ setupUserName
+} from "./functions";
+
+export {
+ API_URL,
+ STORAGE_URL,
+ getRecentMessages,
+ getOrgMembers,
+ getFixedRandomColor,
+ cleanMessageText,
+ setupUserName
+};
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 06/13] feat(lib/functions): add getRepliedMessage() function
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (4 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 05/13] feat(lib): add newly created lib constants variables and functions Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 07/13] feat(lib/functions): add dateFormat() function Muhammad Rizki
` (6 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This commit introduces the getRepliedMessage() function,
designed to retrieve message data that is being replied to by the user.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/lib/functions.ts | 9 +++++++++
src/lib/index.ts | 6 ++++--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/src/lib/functions.ts b/src/lib/functions.ts
index 0357e6b..510f13e 100644
--- a/src/lib/functions.ts
+++ b/src/lib/functions.ts
@@ -93,3 +93,12 @@ export const setupUserName = (first: string, last: string | null) => {
}
return [ firstName, lastName ];
}
+
+export const getRepliedMessage = (
+ current: RecentMessagesReturnType,
+ messages: RecentMessagesReturnType[]
+): RecentMessagesReturnType[] => {
+ return messages.filter(msg => {
+ return msg.message_id === current.reply_to_message_id
+ });
+}
diff --git a/src/lib/index.ts b/src/lib/index.ts
index e8a9d9b..b62f0bd 100644
--- a/src/lib/index.ts
+++ b/src/lib/index.ts
@@ -8,7 +8,8 @@ import {
getOrgMembers,
getFixedRandomColor,
cleanMessageText,
- setupUserName
+ setupUserName,
+ getRepliedMessage
} from "./functions";
export {
@@ -18,5 +19,6 @@ export {
getOrgMembers,
getFixedRandomColor,
cleanMessageText,
- setupUserName
+ setupUserName,
+ getRepliedMessage
};
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 07/13] feat(lib/functions): add dateFormat() function
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (5 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 06/13] feat(lib/functions): add getRepliedMessage() function Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 08/13] feat(components): add <OrganizationMembers/> component Muhammad Rizki
` (5 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This commit introduces the dateFormat() function, which is used to
format datetime string returned by the API response. The formatted date
appears as follows: "Today at 09:00", "Yesterday at 09:00",
"Oct 02 at 09:00", and so on.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/lib/functions.ts | 29 +++++++++++++++++++++++++++++
src/lib/index.ts | 6 ++++--
2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/src/lib/functions.ts b/src/lib/functions.ts
index 510f13e..2928824 100644
--- a/src/lib/functions.ts
+++ b/src/lib/functions.ts
@@ -102,3 +102,32 @@ export const getRepliedMessage = (
return msg.message_id === current.reply_to_message_id
});
}
+
+export const dateFormat = (date: string, amPm: boolean = false): string => {
+ const ts = new Date(date);
+ const today = new Date();
+
+ const tsDate = ts.getDate();
+ const todayDate = today.getDate();
+
+ const tsMonth = ts.getMonth();
+ const todayMonth = today.getMonth();
+
+ const tsYear = ts.getFullYear();
+ const todayYear = today.getFullYear();
+
+ const calc = todayDate - tsDate;
+ const localeTime = ts.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: amPm });
+
+ if (tsDate === todayDate &&tsMonth === todayMonth && tsYear === todayYear) {
+ return `Today at ${localeTime}`;
+ } else if (calc === 1 && tsMonth === todayMonth && tsYear === todayYear) {
+ return `Yesterday at ${localeTime}`;
+ } else if (calc === -1 && tsMonth === todayMonth && tsYear === todayYear) {
+ return `Tomorrow at ${localeTime}`;
+ } else if (tsYear === todayYear) {
+ return `${tsDate} ${ts.toLocaleString('en-US', { month: 'short' })} at ${localeTime}`;
+ } else {
+ return `${ts.toLocaleString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })} at ${localeTime}`;
+ }
+}
diff --git a/src/lib/index.ts b/src/lib/index.ts
index b62f0bd..2c71df5 100644
--- a/src/lib/index.ts
+++ b/src/lib/index.ts
@@ -9,7 +9,8 @@ import {
getFixedRandomColor,
cleanMessageText,
setupUserName,
- getRepliedMessage
+ getRepliedMessage,
+ dateFormat
} from "./functions";
export {
@@ -20,5 +21,6 @@ export {
getFixedRandomColor,
cleanMessageText,
setupUserName,
- getRepliedMessage
+ getRepliedMessage,
+ dateFormat
};
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 08/13] feat(components): add <OrganizationMembers/> component
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (6 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 07/13] feat(lib/functions): add dateFormat() function Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 09/13] feat(components): add <RecentMessages/> component Muhammad Rizki
` (4 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This component UI will display GitHub organization members.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/lib/components/OrganizationMembers.svelte | 41 +++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 src/lib/components/OrganizationMembers.svelte
diff --git a/src/lib/components/OrganizationMembers.svelte b/src/lib/components/OrganizationMembers.svelte
new file mode 100644
index 0000000..2443378
--- /dev/null
+++ b/src/lib/components/OrganizationMembers.svelte
@@ -0,0 +1,41 @@
+<script lang="ts">
+ import type { GitHubOrgsAPIResponseType } from "$types";
+
+ export let data: GitHubOrgsAPIResponseType[];
+</script>
+
+
+<div
+ class="border border-neutral-800 rounded-xl overflow-hidden
+ max-w-xs md:max-w-lg lg:max-w-3xl xl:w-[20rem]"
+>
+ <div class="flex px-5 py-2 border-b border-neutral-800 justify-between items-center">
+ <h1 class="text-lg font-bold text-center w-full">Member List</h1>
+ </div>
+ <div class="px-3 py-2 space-y-1 text-sm max-h-[300px] overflow-y-auto">
+ {#each data as member}
+ <a
+ href={member.html_url}
+ class="flex items-center space-x-3 p-1 rounded-lg hover:bg-neutral-800"
+ >
+ <img
+ src={member.avatar_url}
+ alt="{member.login} | Organization Member"
+ class="rounded-full w-10"
+ >
+ <div class="truncate text-sky-500">@{member.login}</div>
+ </a>
+ {/each}
+ </div>
+ <a href="https://github.com/orgs/gnuweeb/people" draggable="false" target="_blank">
+ <div
+ class="p-3 border-t border-neutral-800 hover:bg-neutral-800
+ flex justify-center items-center w-full"
+ >
+ <span class="select-none font-semibold text-sky-500 mr-1">View on GitHub</span>
+ <svg class="w-3 h-3 text-neutral-500" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
+ <path d="M 40.960938 4.9804688 A 2.0002 2.0002 0 0 0 40.740234 5 L 28 5 A 2.0002 2.0002 0 1 0 28 9 L 36.171875 9 L 22.585938 22.585938 A 2.0002 2.0002 0 1 0 25.414062 25.414062 L 39 11.828125 L 39 20 A 2.0002 2.0002 0 1 0 43 20 L 43 7.2460938 A 2.0002 2.0002 0 0 0 40.960938 4.9804688 z M 12.5 8 C 8.3826878 8 5 11.382688 5 15.5 L 5 35.5 C 5 39.617312 8.3826878 43 12.5 43 L 32.5 43 C 36.617312 43 40 39.617312 40 35.5 L 40 26 A 2.0002 2.0002 0 1 0 36 26 L 36 35.5 C 36 37.446688 34.446688 39 32.5 39 L 12.5 39 C 10.553312 39 9 37.446688 9 35.5 L 9 15.5 C 9 13.553312 10.553312 12 12.5 12 L 22 12 A 2.0002 2.0002 0 1 0 22 8 L 12.5 8 z"></path>
+ </svg>
+ </div>
+ </a>
+</div>
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 09/13] feat(components): add <RecentMessages/> component
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (7 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 08/13] feat(components): add <OrganizationMembers/> component Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 10/13] feat(routes): add +page.server.ts Muhammad Rizki
` (3 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This commit includes the <RecentMessages/> component, which is for
displaying recent messages from the GNU/Weeb's Telegram group chat.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/lib/components/RecentMessages.svelte | 249 +++++++++++++++++++++++
1 file changed, 249 insertions(+)
create mode 100644 src/lib/components/RecentMessages.svelte
diff --git a/src/lib/components/RecentMessages.svelte b/src/lib/components/RecentMessages.svelte
new file mode 100644
index 0000000..25fb0eb
--- /dev/null
+++ b/src/lib/components/RecentMessages.svelte
@@ -0,0 +1,249 @@
+<script lang="ts">
+ import { STORAGE_URL } from "$lib";
+ import { cleanMessageText, getFixedRandomColor, setupUserName } from "$lib";
+ import { dateFormat, getRepliedMessage } from "$lib/functions";
+ import type { RecentMessagesReturnType } from "$types";
+ import { onMount } from "svelte";
+
+ export let data: RecentMessagesReturnType[];
+ export let innerWidth: number;
+
+ let chatRootEl: HTMLDivElement;
+ let err: any;
+
+ const gotoReply = (msgId: number) => {
+ const targetReply = document.getElementById(msgId.toString());
+ const highlightReply = document.getElementById(`${msgId}-highlight`);
+
+ targetReply?.scrollIntoView({
+ behavior: innerWidth >= 1280 ? "smooth" : "instant",
+ block: "end",
+ inline: "nearest"
+ });
+
+ highlightReply?.classList.add(
+ "!bg-neutral-700", "!scale-105"
+ );
+
+ setTimeout(() => {
+ highlightReply?.classList.remove(
+ "!bg-neutral-700", "!scale-105"
+ );
+ }, 2000);
+ }
+
+ onMount(() => {
+ chatRootEl.lastElementChild?.scrollIntoView({
+ behavior: "smooth", block: "end", inline: "nearest"
+ });
+ })
+</script>
+
+
+<div
+ class="border border-neutral-800 rounded-xl overflow-hidden
+ max-w-xs md:max-w-lg lg:max-w-3xl xl:w-[20rem]"
+>
+
+ <div class="flex px-5 py-2 border-b border-neutral-800 justify-between items-center">
+ <h1 class="text-lg font-bold text-center w-full">Recent Group Messages</h1>
+ </div>
+
+ <div
+ bind:this={chatRootEl}
+ class="px-3 py-2 space-y-1 text-sm max-h-[500px] overflow-y-auto"
+ >
+
+ {#if data.length === 0}
+ <div class="text-red-500 italic text-center p-3">
+ Cannot Connect to the API.<br>API Connection failure.
+ </div>
+
+ {:else}
+ {#each data as msg}
+
+ <div
+ id={msg.message_id.toString()}
+ class="chat chat-start w-full"
+ >
+
+ <div class="chat-image avatar">
+ <div class="w-10 rounded-full">
+ <img
+ src={STORAGE_URL + msg.user_photo}
+ alt=""
+ draggable="false"
+ >
+ </div>
+ </div>
+
+ <div
+ id={msg.message_id.toString() + "-highlight"}
+ class="chat-bubble transition before:transition duration-500
+ before:duration-500 ease-in-out before:ease-in-out
+ delay-200 before:delay-200"
+ >
+
+ <div
+ class="chat-header font-semibold pb-1 line-clamp-1
+ {getFixedRandomColor(msg.first_name)[0]}"
+ >
+ {setupUserName(msg.first_name, msg.last_name).join("")}
+ </div>
+
+ {#if msg.reply_to_message_id !== null}
+ {#each getRepliedMessage(msg, data) as rpl}
+
+ <button
+ on:click={() => gotoReply(msg.reply_to_message_id || 0)}
+ class="flex flex-col w-full !my-2 py-1 pl-2 border-l-2
+ text-start text-sm text-neutral-300 text-opacity-80
+ hover:bg-neutral-800 rounded-r-md rounded-l-sm
+ {getFixedRandomColor(rpl.first_name)[1]}"
+ >
+ <span class="line-clamp-1 font-semibold not-italic select-none
+ {getFixedRandomColor(rpl.first_name)[0]}"
+ >
+ {setupUserName(rpl.first_name, rpl.last_name).join("")}
+ </span>
+ <span class="line-clamp-1 max-w-[200px] xl:max-w-[150px] max-h-min text-start">
+ {cleanMessageText(rpl.text !== null ? rpl.text : "Photo")}
+ </span>
+ </button>
+
+ {/each}
+ {/if}
+
+ {#if msg.message_type === "text"}
+ <div
+ class="text-neutral-300 max-w-[200px] xl:max-w-[150px] max-h-min
+ line-clamp-2"
+ >
+ {cleanMessageText(msg.text !== null ? msg.text : "")}
+ </div>
+
+ {:else if msg.message_type === "photo"}
+ <div>
+ <div class="relative">
+ <img
+ src={STORAGE_URL + msg.file}
+ alt=""
+ width="250"
+ class="rounded-md mt-1 relative"
+ >
+ <a
+ href={STORAGE_URL + msg.file}
+ target="_blank"
+ draggable="false"
+ class="absolute top-0 flex items-center justify-center
+ w-full h-full rounded-md hover:bg-neutral-900
+ uppercase hover:bg-opacity-60 transition duration-200
+ ease-in-out font-bold text-xl text-white opacity-0
+ hover:opacity-100 select-none"
+ >
+ See
+ </a>
+ </div>
+
+ {#if msg.text !== null}
+ <div class="text-neutral-300 line-clamp-2 max-w-[200px] xl:max-w-[150px] mt-2">
+ {cleanMessageText(msg.text)}
+ </div>
+
+ {/if}
+ </div>
+
+ {/if}
+
+ <div class="flex items-center justify-between pt-2 space-x-3">
+ <a
+ href="https://t.me/gnuweeb/{msg.message_id}"
+ draggable="false"
+ target="_blank"
+ class="text-xs text-sky-400 opacity-70 font-semibold select-none"
+ >
+ Read more
+ </a>
+ <div class="flex justify-end space-x-1 text-xs opacity-70">
+ <time datetime={msg.date}>{dateFormat(msg.date)}</time>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+ {/each}
+ {/if}
+
+ </div>
+
+ <a href="https://t.me/gnuweeb" draggable="false" target="_blank">
+ <div
+ class="p-3 border-t border-neutral-800 hover:bg-neutral-800
+ flex justify-center items-center w-full"
+ >
+ <span class="select-none font-semibold text-sky-500 mr-1">Join</span>
+ <svg class="w-3 h-3 text-neutral-500" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
+ <path d="M 40.960938 4.9804688 A 2.0002 2.0002 0 0 0 40.740234 5 L 28 5 A 2.0002 2.0002 0 1 0 28 9 L 36.171875 9 L 22.585938 22.585938 A 2.0002 2.0002 0 1 0 25.414062 25.414062 L 39 11.828125 L 39 20 A 2.0002 2.0002 0 1 0 43 20 L 43 7.2460938 A 2.0002 2.0002 0 0 0 40.960938 4.9804688 z M 12.5 8 C 8.3826878 8 5 11.382688 5 15.5 L 5 35.5 C 5 39.617312 8.3826878 43 12.5 43 L 32.5 43 C 36.617312 43 40 39.617312 40 35.5 L 40 26 A 2.0002 2.0002 0 1 0 36 26 L 36 35.5 C 36 37.446688 34.446688 39 32.5 39 L 12.5 39 C 10.553312 39 9 37.446688 9 35.5 L 9 15.5 C 9 13.553312 10.553312 12 12.5 12 L 22 12 A 2.0002 2.0002 0 1 0 22 8 L 12.5 8 z"></path>
+ </svg>
+ </div>
+ </a>
+
+</div>
+
+
+<style lang="postcss">
+ .chat {
+ @apply grid gap-x-3 py-1
+ }
+
+ .chat-start {
+ @apply place-items-start grid-cols-[auto,1fr];
+ }
+
+ .chat-image {
+ @apply row-span-2 self-end;
+ }
+
+ .chat-start .chat-image {
+ @apply col-start-1;
+ }
+
+ .chat-start .chat-header {
+ @apply col-start-2;
+ }
+
+ .chat-bubble {
+ @apply relative block w-fit px-4 py-2 max-w-[90%] rounded-2xl
+ min-h-[2.75rem] min-w-[2.75rem] bg-neutral-900 text-neutral-500;
+ }
+
+ .chat-bubble::before {
+ @apply absolute bottom-0 h-3 w-3 bg-inherit content-[""];
+ mask-size: contain;
+ -webkit-mask-size: contain;
+ mask-repeat: no-repeat;
+ -webkit-mask-repeat: no-repeat;
+ mask-position: center;
+ -webkit-mask-position: center;
+ }
+
+ .chat-start .chat-bubble {
+ @apply col-start-2 rounded-bl-none;
+ }
+
+ .chat-start .chat-bubble::before {
+ @apply content-[""] -left-3;
+ mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
+ -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
+ }
+
+ .avatar {
+ @apply relative inline-flex;
+ }
+
+ .avatar > div {
+ @apply block aspect-square overflow-hidden;
+ }
+</style>
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 10/13] feat(routes): add +page.server.ts
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (8 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 09/13] feat(components): add <RecentMessages/> component Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 11/13] feat(routes/page): add +page.svelte Muhammad Rizki
` (2 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This commit adds +page.server.ts, which is responsible for data fetching
from the API on the server-side. It will be loaded with
`export let data;` in +page.svelte.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/routes/+page.server.ts | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 src/routes/+page.server.ts
diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts
new file mode 100644
index 0000000..d845c51
--- /dev/null
+++ b/src/routes/+page.server.ts
@@ -0,0 +1,13 @@
+import { getOrgMembers, getRecentMessages } from "$lib";
+import type { PageServerLoad } from "./$types";
+
+
+export const load = (async () => {
+ const memberListData = await getOrgMembers();
+ const recentMsgData = await getRecentMessages();
+
+ return {
+ memberListData,
+ recentMsgData
+ }
+}) satisfies PageServerLoad;
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 11/13] feat(routes/page): add +page.svelte
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (9 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 10/13] feat(routes): add +page.server.ts Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 12/13] chore(README): update README.md Muhammad Rizki
2023-10-03 2:51 ` [PATCH v1 13/13] chore: remove unused files Muhammad Rizki
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This commit adds +page.svelte, a file responsible for displaying the
main page UI. It loads the fetched data from +page.server.svelte using
`export let data;` and then renders it using HTML elements.
In this commit, we've included logic to bind innerWidth to manage the
screen size for the recent message UI. We use this logic to control the
visibility of the recent message UI based on whether the screen size is
less than or equal to 1280 pixels or higher. This approach is also
applied to the <RecentMessages/> component to handle scroll behavior
accordingly.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/routes/+page.svelte | 259 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 259 insertions(+)
create mode 100644 src/routes/+page.svelte
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
new file mode 100644
index 0000000..c00cf0e
--- /dev/null
+++ b/src/routes/+page.svelte
@@ -0,0 +1,259 @@
+<script lang="ts">
+ import OrganizationMembers from "$components/OrganizationMembers.svelte";
+ import RecentMessages from "$components/RecentMessages.svelte";
+
+ export let data;
+ let copyBtnEl: HTMLButtonElement;
+ let copyTxtEl: HTMLButtonElement;
+ let innerWidth: number = 9999;
+
+ const copyText = () => {
+ navigator.clipboard.writeText(copyTxtEl.innerText);
+ copyBtnEl.innerText = "Copied!";
+ copyBtnEl.classList.add("bg-neutral-800");
+ setTimeout(function () {
+ copyBtnEl.innerText = "Copy";
+ copyBtnEl.classList.remove("bg-neutral-800");
+ }, 3000);
+ }
+</script>
+
+
+<!-- RECENT MESSAGES SECTION | RIGHT -->
+{#if innerWidth >= 1280}
+ <section class="hidden xl:flex flex-col py-5 max-h-screen">
+ <RecentMessages data={data.recentMsgData} innerWidth={innerWidth}/>
+ </section>
+{/if}
+
+<!-- CONTENT PROFILE | CENTER -->
+<section class="flex flex-col space-y-3 px-3">
+
+ <!-- PROFILE SECTION -->
+ <div class="border border-neutral-800 rounded-b-xl overflow-hidden max-w-xs md:max-w-lg lg:max-w-3xl">
+ <img
+ src="/img/profile-cover.jpg"
+ alt=""
+ draggable="false"
+ style="filter: brightness(70%);"
+ >
+ <div class="relative flex flex-col px-5 py-3 space-x-3 space-y-3">
+ <div class="flex space-x-1 md:space-x-2 lg:space-x-3 pb-5 border-b border-neutral-800">
+ <div class="-mt-16">
+ <img
+ src="https://github.com/GNUWeeb.png"
+ alt="GNU/Weeb's GitHub Profile"
+ draggable="false"
+ class="rounded-full w-44 border-4 border-neutral-950 bg-neutral-950"
+ />
+ </div>
+ <div class="flex justify-between w-full">
+ <div class="text-2xl md:text-3xl font-bold">
+ GNU/Weeb
+ </div>
+ <div>
+ <a
+ href="https://github.com/GNUWeeb"
+ target="_blank"
+ title="View GNU/Weeb's Organization on GitHub"
+ class="relative bottom-1 p-2 rounded-full hover:bg-neutral-800 flex items-center
+ justify-center transition-colors duration-300 ease-in-out"
+ draggable="false"
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ class="w-5 h-5 md:w-6 md:h-6 lg:w-7 lg:h-7"
+ >
+ <path
+ d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"
+ />
+ <path d="M9 18c-4.51 2-5-2-7-2" />
+ </svg>
+ <span class="sr-only">GitHub</span>
+ </a>
+ </div>
+ </div>
+ </div>
+ <div class="py-1 space-y-1">
+ <h2 class="font-bold text-2xl select-none">About</h2>
+ <p class="w-full opacity-70">
+ We are working to build a community through open source technology.
+ </p>
+ <blockquote
+ class="px-3 border-l-4 pl-3 !my-7 text-sm border-neutral-200"
+ >
+ <span class="not-italic font-bold select-none">Note:</span><br />
+ <span class="opacity-80 pb-1">
+ Members on GitHub must have two-factor auth.
+ </span>
+ </blockquote>
+ </div>
+ </div>
+ </div>
+
+ <!-- RECENT MESSAGES SECTION - MOBILE | RIGHT -->
+ {#if innerWidth < 1280}
+ <div class="flex flex-col max-h-screen">
+ <RecentMessages data={data.recentMsgData} innerWidth={innerWidth}/>
+ </div>
+ {/if}
+
+ <!-- MEMBER LIST SECTION - MOBILE | RIGHT -->
+ <div class="flex xl:hidden flex-col max-h-screen">
+ <OrganizationMembers data={data.memberListData}/>
+ </div>
+
+ <!-- MAILING LIST SECTION -->
+ <div class="border border-neutral-800 rounded-xl overflow-hidden max-w-3xl">
+ <div
+ class="flex px-5 py-2 border-b border-neutral-800 justify-between items-center"
+ >
+ <h1 class="text-lg font-bold text-center w-full select-none">Mailing List</h1>
+ </div>
+ <div class="px-5 py-3 text-sm">
+ <div class="overflow-hidden flex items-center justify-between border rounded-lg
+ border-neutral-900 font-mono"
+ >
+ <button
+ bind:this={copyTxtEl} on:click={copyText}
+ class="px-3 py-2 select-none cursor-pointer w-full"
+ >
+ [email protected]
+ </button>
+ <button
+ bind:this={copyBtnEl} on:click={copyText}
+ class="w-fit py-2 px-3 border-l border-neutral-900 hover:border-neutral-800
+ hover:bg-neutral-800 transition-colors duration-300 ease-in-out"
+ title="Copy to Clipboard"
+
+ >
+ Copy
+ </button>
+ </div>
+ </div>
+ </div>
+
+ <!-- USEFUL LINKS SECTION -->
+ <div class="border border-neutral-800 rounded-xl overflow-hidden max-w-3xl">
+ <div
+ class="flex px-5 py-2 border-b border-neutral-800 justify-between items-center"
+ >
+ <h1 class="text-lg font-bold text-center w-full select-none">Useful Links</h1>
+ </div>
+ <div class="px-5 py-3 grid gap-3 grid-cols-2 text-sm">
+ <a
+ href="https://t.me/GNUWeeb"
+ target="_blank"
+ draggable="false"
+ class="flex items-center gap-2 justify-center px-3 py-2 border rounded-lg
+ border-neutral-900 hover:border-neutral-800 hover:bg-neutral-800
+ transition-colors duration-300 ease-in-out"
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ class="w-5 h-5"
+ >
+ <path d="m22 2-7 20-4-9-9-4Z" />
+ <path d="M22 2 11 13" />
+ </svg>
+ <span class="select-none">Telegram</span>
+ </a>
+ <a
+ href="https://lore.gnuweeb.org/gwml"
+ target="_blank"
+ draggable="false"
+ class="flex items-center gap-2 justify-center px-3 py-2 border rounded-lg
+ border-neutral-900 hover:border-neutral-800 hover:bg-neutral-800
+ transition-colors duration-300 ease-in-out"
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ class="w-5 h-5"
+ >
+ <path
+ d="M8 21h12a2 2 0 0 0 2-2v-2H10v2a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v3h4"
+ />
+ <path d="M19 17V5a2 2 0 0 0-2-2H4" />
+ <path d="M15 8h-5" />
+ <path d="M15 12h-5" />
+ </svg>
+ <span class="select-none">GWML Lore</span>
+ </a>
+ <a
+ href="https://discord.gg/GyRxNzK3Zs"
+ target="_blank"
+ draggable="false"
+ class="flex items-center gap-2 justify-center px-3 py-2 border rounded-lg
+ border-neutral-900 hover:border-neutral-800 hover:bg-neutral-800
+ transition-colors duration-300 ease-in-out"
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ class="w-5 h-5"
+ >
+ <path
+ d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"
+ />
+ <path
+ d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
+ />
+ </svg>
+ <span class="select-none">Discord</span>
+ </a>
+ <a
+ href="https://social.gnuweeb.org/"
+ target="_blank"
+ draggable="false"
+ class="flex items-center gap-2 justify-center px-3 py-2 border rounded-lg
+ border-neutral-900 hover:border-neutral-800 hover:bg-neutral-800
+ transition-colors duration-300 ease-in-out"
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="none"
+ stroke="currentColor"
+ stroke-width="2"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ class="w-5 h-5"
+ >
+ <path d="m3 21 1.9-5.7a8.5 8.5 0 1 1 3.8 3.8z" />
+ </svg>
+ <span class="select-none">GW Social</span>
+ </a>
+ </div>
+ </div>
+
+</section>
+
+<!-- MEMBER LIST SECTION | RIGHT -->
+<section class="hidden xl:flex flex-col py-5 max-h-screen">
+ <OrganizationMembers data={data.memberListData}/>
+</section>
+
+<svelte:window bind:innerWidth/>
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v1 12/13] chore(README): update README.md
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (10 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 11/13] feat(routes/page): add +page.svelte Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
2023-10-05 19:29 ` Ammar Faizi
2023-10-03 2:51 ` [PATCH v1 13/13] chore: remove unused files Muhammad Rizki
12 siblings, 1 reply; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This commit includes updates to the project instructions and project
structure in the README.md file.
Signed-off-by: Muhammad Rizki <[email protected]>
---
README.md | 36 ++++++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index edf3c86..861add0 100644
--- a/README.md
+++ b/README.md
@@ -1,30 +1,45 @@
# GNU/Weeb's Landing Page
-GNU/Weeb's simple landing page.
+GNU/Weeb's landing page made with svelte/kit.
## Project Structure
```
-/ - index.html (Main page)
- - style.css (Tailwind CSS)
+/ - src/ (App source)
+ - lib/ (App library)
+ - routes/ (App routes)
+ - components/ (App UI components)
+ - app.css (App CSS styles)
+ - app.d.ts (App types)
+ - app.html (App root HTML)
- package.json (Dev dependencies)
- *package-lock.json (npm lockfile)
- static/ (Static files)
- favicon.ico (Favicon)
- **dist/ (Build directory)
- - build.js (Build script)
+ - **.svelte-kit/ (Compiled svelte/kit directory)
- .gitignore (Git ignore)
+ . .editorconfig (IDE/Editor config file)
+ - .eslintignore (ES lint ignore file)
+ - .eslintrc.cjs (ES lint config file)
+ - .prettierignore (Prettier ignore file)
+ - .prettierrc (Prettier config file)
+ - postcss.config.js (PostCSS config file)
+ - svelte.config.js (Svelte config file)
+ - tailwind.config.js (Tailwind config file)
+ - tsconfig.json (TypeScript compiler config file)
+ - vite.config.ts (Vite config file)
/** Legend:
* (*) => Only available after npm install
- * (**) => Only available after npm build
+ * (**) => Only available after npm run build
*/
```
## Development
-> You will need `nodejs` (minimum version: 16) and `npm` package to run the dev server locally
+> You will need `nodejs` (minimum version: 16), `TypeScript` (minimum version: 5) and `npm` package to run the dev server locally.
### Installing dependencies
@@ -52,6 +67,15 @@ npm run build
This will copy all the required files into the `dist` directory.
+## Production Build Server
+
+To run the production build node server, issue this command:
+
+```bash
+node dist
+# Listening on 0.0.0.0:3000
+```
+
## License
BSD 3-Clause License.
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v1 12/13] chore(README): update README.md
2023-10-03 2:51 ` [PATCH v1 12/13] chore(README): update README.md Muhammad Rizki
@ 2023-10-05 19:29 ` Ammar Faizi
2023-10-07 5:36 ` Muhammad Rizki
0 siblings, 1 reply; 16+ messages in thread
From: Ammar Faizi @ 2023-10-05 19:29 UTC (permalink / raw)
To: Muhammad Rizki
Cc: Alviro Iskandar Setiawan, Irvan Malik Azantha, Memet Zx,
GNU/Weeb Mailing List
On 10/3/23 9:51 AM, Muhammad Rizki wrote:
> +## Production Build Server
> +
> +To run the production build node server, issue this command:
> +
> +```bash
> +node dist
> +# Listening on 0.0.0.0:3000
> +```
Why is this needed? I don't see the need to run an additional web
server to serve a static website. I expect to have only nginx to run
https://www.gnuweeb.org .
You may argue you need extra backend code to fetch the API in patch
#10, but why should you do that in the backend? Can't you move that
functionality to the client side JavaScript?
I will only take your series once you can demonstrate a good reason
why you are doing this.
--
Ammar Faizi
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v1 12/13] chore(README): update README.md
2023-10-05 19:29 ` Ammar Faizi
@ 2023-10-07 5:36 ` Muhammad Rizki
0 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-07 5:36 UTC (permalink / raw)
To: Ammar Faizi
Cc: Alviro Iskandar Setiawan, Irvan Malik Azantha, Memet Zx,
GNU/Weeb Mailing List
On 06/10/2023 02.29, Ammar Faizi wrote:
> On 10/3/23 9:51 AM, Muhammad Rizki wrote:
>> +## Production Build Server
>> +
>> +To run the production build node server, issue this command:
>> +
>> +```bash
>> +node dist
>> +# Listening on 0.0.0.0:3000
>> +```
>
> Why is this needed? I don't see the need to run an additional web
> server to serve a static website. I expect to have only nginx to run
> https://www.gnuweeb.org .
OK
>
> You may argue you need extra backend code to fetch the API in patch
> #10, but why should you do that in the backend? Can't you move that
> functionality to the client side JavaScript?
>
Sure, just change the +page.server.ts to +page.ts in order to become
client-side, I will make v2 for it.
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v1 13/13] chore: remove unused files
2023-10-03 2:51 [PATCH v1 00/13] GNU/Weeb Web Migration to SvelteKit Muhammad Rizki
` (11 preceding siblings ...)
2023-10-03 2:51 ` [PATCH v1 12/13] chore(README): update README.md Muhammad Rizki
@ 2023-10-03 2:51 ` Muhammad Rizki
12 siblings, 0 replies; 16+ messages in thread
From: Muhammad Rizki @ 2023-10-03 2:51 UTC (permalink / raw)
To: Ammar Faizi
Cc: Muhammad Rizki, Alviro Iskandar Setiawan, Irvan Malik Azantha,
Memet Zx, GNU/Weeb Mailing List
This commit removes the unused files `build.js`, `index.html`, and
`style.css`, as they are no longer in use.
Signed-off-by: Muhammad Rizki <[email protected]>
---
build.js | 37 ---
index.html | 644 -----------------------------------------------------
style.css | 57 -----
3 files changed, 738 deletions(-)
delete mode 100644 build.js
delete mode 100644 index.html
delete mode 100644 style.css
diff --git a/build.js b/build.js
deleted file mode 100644
index 1c85989..0000000
--- a/build.js
+++ /dev/null
@@ -1,37 +0,0 @@
-const { minify } = require("html-minifier-terser");
-const fs = require("fs");
-const path = require("path");
-
-const htmlMinifierOptions = {
- caseSensitive: true,
- collapseBooleanAttributes: true,
- collapseInlineTagWhitespace: true,
- collapseWhitespace: true,
- html5: true,
- minifyJS: true,
- minifyCSS: true,
- removeComments: true,
-};
-
-const htmlMinify = (html) => minify(html, htmlMinifierOptions);
-
-const htmlMinifyFile = (file) => {
- const filePath = path.join(__dirname, file);
- const html = fs.readFileSync(filePath, "utf8");
- const minifiedHtml = htmlMinify(html)
- .then((minifiedHtml) => {
- fs.writeFileSync(filePath, minifiedHtml);
- })
- .catch((err) => {
- console.log(`[ERROR] ${err}`);
- })
- .finally(() => {
- console.log(`[INFO] ${filePath} minified.`);
- });
-
- return () => minifiedHtml;
-};
-
-htmlMinifyFile("dist/index.html");
-
-console.log("HTML minified.");
diff --git a/index.html b/index.html
deleted file mode 100644
index 5c6eef3..0000000
--- a/index.html
+++ /dev/null
@@ -1,644 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <meta http-equiv="X-UA-Compatible" content="ie=edge" />
- <meta property="og:title" content="GNU/Weeb" />
- <meta property="og:description" content="We are working to build community through open source technology." />
- <meta property="og:image" content="./static/og-image.png" />
- <meta property="og:url" content="https://www.gnuweeb.org/" />
- <meta property="og:type" content="website" />
- <meta property="og:site_name" content="GNU/Weeb" />
- <meta name="twitter:card" content="summary_large_image" />
- <meta name="description" content="We are working to build community through open source technology.">
-
- <title>GNU/Weeb Landing</title>
-
- <link rel="stylesheet" href="dist/style.css" />
- <link rel="shortcut icon" href="./static/favicon.ico" type="image/x-icon" />
- <link rel="canonical" href="https://www.gnuweeb.org/" />
- <link
- rel="apple-touch-icon"
- sizes="180x180"
- href="./static/apple-touch-icon.png"
- />
- <link
- rel="icon"
- type="image/png"
- sizes="32x32"
- href="./static/favicon-32x32.png"
- />
- <link
- rel="icon"
- type="image/png"
- sizes="16x16"
- href="./static/favicon-16x16.png"
- />
- <link rel="manifest" href="./static/site.webmanifest" />
- </head>
-
- <body class="w-full px-20 bg-neutral-950 text-neutral-200">
- <main class="flex justify-center w-full min-h-screen space-x-3">
-
- <!-- RECENT MESSAGES SECTION | RIGHT -->
- <section class="hidden xl:flex flex-col space-y-3 py-5 max-h-screen">
- <section class="border border-neutral-800 rounded-xl overflow-hidden w-[20rem]">
- <div class="flex px-5 py-2 border-b border-neutral-800 justify-between items-center">
- <h1 class="text-lg font-bold text-center w-full">Recent Group Messages</h1>
- </div>
- <div id="recent-messages" class="px-3 py-2 space-y-1 text-sm max-h-[300px] overflow-y-auto">
- </div>
- <a href="https://t.me/gnuweeb" draggable="false" target="_blank">
- <div
- class="p-3 border-t border-neutral-800 hover:bg-neutral-800
- flex justify-center items-center w-full"
- >
- <span class="select-none font-semibold text-sky-500 mr-1">Join</span>
- <svg class="w-3 h-3 text-neutral-500" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
- <path d="M 40.960938 4.9804688 A 2.0002 2.0002 0 0 0 40.740234 5 L 28 5 A 2.0002 2.0002 0 1 0 28 9 L 36.171875 9 L 22.585938 22.585938 A 2.0002 2.0002 0 1 0 25.414062 25.414062 L 39 11.828125 L 39 20 A 2.0002 2.0002 0 1 0 43 20 L 43 7.2460938 A 2.0002 2.0002 0 0 0 40.960938 4.9804688 z M 12.5 8 C 8.3826878 8 5 11.382688 5 15.5 L 5 35.5 C 5 39.617312 8.3826878 43 12.5 43 L 32.5 43 C 36.617312 43 40 39.617312 40 35.5 L 40 26 A 2.0002 2.0002 0 1 0 36 26 L 36 35.5 C 36 37.446688 34.446688 39 32.5 39 L 12.5 39 C 10.553312 39 9 37.446688 9 35.5 L 9 15.5 C 9 13.553312 10.553312 12 12.5 12 L 22 12 A 2.0002 2.0002 0 1 0 22 8 L 12.5 8 z"></path>
- </svg>
- </div>
- </a>
- </section>
- </section>
-
- <!-- CONTENT PROFILE | CENTER -->
- <section class="flex flex-col space-y-3">
-
- <!-- PROFILE SECTION -->
- <section class="border border-neutral-800 rounded-b-xl overflow-hidden max-w-3xl">
- <img
- src="./static/img/profile-cover.jpg"
- alt=""
- draggable="false"
- style="filter: brightness(70%);"
- >
- <div class="relative flex flex-col px-5 py-3 space-x-3 space-y-3">
- <div class="flex space-x-1 md:space-x-2 lg:space-x-3 pb-5 border-b border-neutral-800">
- <div class="-mt-16">
- <img
- src="https://github.com/GNUWeeb.png"
- alt="GNU/Weeb's GitHub Profile Picture"
- draggable="false"
- class="rounded-full w-44 border-4 border-neutral-950 bg-neutral-950"
- />
- </div>
- <div class="flex justify-between w-full">
- <div class="text-2xl md:text-3xl font-bold">
- GNU/Weeb
- </div>
- <div>
- <a
- href="https://github.com/GNUWeeb"
- target="_blank"
- title="View GNU/Weeb's Organization on GitHub"
- class="relative bottom-1 p-2 rounded-full hover:bg-neutral-800 flex items-center
- justify-center transition-colors duration-300 ease-in-out"
- draggable="false"
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 24 24"
- fill="none"
- stroke="currentColor"
- stroke-width="2"
- stroke-linecap="round"
- stroke-linejoin="round"
- class="w-5 h-5 md:w-6 md:h-6 lg:w-7 lg:h-7"
- >
- <path
- d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"
- />
- <path d="M9 18c-4.51 2-5-2-7-2" />
- </svg>
- <span class="sr-only">GitHub</span>
- </a>
- </div>
- </div>
- </div>
- <div class="py-1 space-y-1">
- <h2 class="font-bold text-2xl select-none">About</h2>
- <p class="w-full opacity-70">
- We are working to build community through open source technology.
- </p>
- <blockquote
- class="w-max px-3 border-l-4 pl-3 !my-7 text-sm border-neutral-200"
- >
- <span class="not-italic font-bold select-none">Note:</span><br />
- <span class="opacity-80">Members on GitHub must have two-factor auth.</span>
- </blockquote>
- </div>
- </div>
- </section>
-
- <!-- MAILING LIST SECTION -->
- <section class="border border-neutral-800 rounded-xl overflow-hidden max-w-3xl">
- <div
- class="flex px-5 py-2 border-b border-neutral-800 justify-between items-center"
- >
- <h1 class="text-lg font-bold text-center w-full select-none">Mailing List</h1>
- </div>
- <div class="px-5 py-3 text-sm">
- <div class="overflow-hidden flex items-center justify-between border rounded-lg
- border-neutral-900 font-mono"
- >
- <p
- id="copy-text"
- class="px-3 py-2 select-none cursor-pointer w-full"
- onclick="copyText()"
- >
- [email protected]
- </p>
- <button
- id="copy-button"
- class="w-fit py-2 px-3 border-l border-neutral-900 hover:border-neutral-800
- hover:bg-neutral-800 transition-colors duration-300 ease-in-out"
- title="Copy to Clipboard"
- onclick="copyText()"
- >
- Copy
- </button>
- </div>
- </div>
- </section>
-
- <!-- USEFUL LINKS SECTION -->
- <section class="border border-neutral-800 rounded-xl overflow-hidden max-w-3xl">
- <div
- class="flex px-5 py-2 border-b border-neutral-800 justify-between items-center"
- >
- <h1 class="text-lg font-bold text-center w-full select-none">Useful Links</h1>
- </div>
- <div class="px-5 py-3 grid gap-3 grid-cols-2 text-sm">
- <a
- href="https://t.me/GNUWeeb"
- target="_blank"
- draggable="false"
- class="flex items-center gap-2 justify-center px-3 py-2 border rounded-lg
- border-neutral-900 hover:border-neutral-800 hover:bg-neutral-800
- transition-colors duration-300 ease-in-out"
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 24 24"
- fill="none"
- stroke="currentColor"
- stroke-width="2"
- stroke-linecap="round"
- stroke-linejoin="round"
- class="w-5 h-5"
- >
- <path d="m22 2-7 20-4-9-9-4Z" />
- <path d="M22 2 11 13" />
- </svg>
- <span class="select-none">Telegram</span>
- </a>
- <a
- href="https://lore.gnuweeb.org/gwml"
- target="_blank"
- draggable="false"
- class="flex items-center gap-2 justify-center px-3 py-2 border rounded-lg
- border-neutral-900 hover:border-neutral-800 hover:bg-neutral-800
- transition-colors duration-300 ease-in-out"
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 24 24"
- fill="none"
- stroke="currentColor"
- stroke-width="2"
- stroke-linecap="round"
- stroke-linejoin="round"
- class="w-5 h-5"
- >
- <path
- d="M8 21h12a2 2 0 0 0 2-2v-2H10v2a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v3h4"
- />
- <path d="M19 17V5a2 2 0 0 0-2-2H4" />
- <path d="M15 8h-5" />
- <path d="M15 12h-5" />
- </svg>
- <span class="select-none">GWML Lore</span>
- </a>
- <a
- href="https://discord.gg/GyRxNzK3Zs"
- target="_blank"
- draggable="false"
- class="flex items-center gap-2 justify-center px-3 py-2 border rounded-lg
- border-neutral-900 hover:border-neutral-800 hover:bg-neutral-800
- transition-colors duration-300 ease-in-out"
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 24 24"
- fill="none"
- stroke="currentColor"
- stroke-width="2"
- stroke-linecap="round"
- stroke-linejoin="round"
- class="w-5 h-5"
- >
- <path
- d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"
- />
- <path
- d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
- />
- </svg>
- <span class="select-none">Discord</span>
- </a>
- <a
- href="https://social.gnuweeb.org/"
- target="_blank"
- draggable="false"
- class="flex items-center gap-2 justify-center px-3 py-2 border rounded-lg
- border-neutral-900 hover:border-neutral-800 hover:bg-neutral-800
- transition-colors duration-300 ease-in-out"
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 24 24"
- fill="none"
- stroke="currentColor"
- stroke-width="2"
- stroke-linecap="round"
- stroke-linejoin="round"
- class="w-5 h-5"
- >
- <path d="m3 21 1.9-5.7a8.5 8.5 0 1 1 3.8 3.8z" />
- </svg>
- <span class="select-none">GW Social</span>
- </a>
- </div>
- </section>
-
- </section>
-
- <!-- MEMBER LIST SECTION | RIGHT -->
- <section class="hidden xl:flex flex-col space-y-3 py-5 max-h-screen">
- <section class="border border-neutral-800 rounded-xl overflow-hidden w-[20rem]">
- <div class="flex px-5 py-2 border-b border-neutral-800 justify-between items-center">
- <h1 class="text-lg font-bold text-center w-full">Member List</h1>
- </div>
- <div id="member-list" class="px-3 py-2 space-y-1 text-sm max-h-[300px] overflow-y-auto"></div>
- <a href="https://github.com/orgs/gnuweeb/people" draggable="false" target="_blank">
- <div
- class="p-3 border-t border-neutral-800 hover:bg-neutral-800
- flex justify-center items-center w-full"
- >
- <span class="select-none font-semibold text-sky-500 mr-1">View on GitHub</span>
- <svg class="w-3 h-3 text-neutral-500" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
- <path d="M 40.960938 4.9804688 A 2.0002 2.0002 0 0 0 40.740234 5 L 28 5 A 2.0002 2.0002 0 1 0 28 9 L 36.171875 9 L 22.585938 22.585938 A 2.0002 2.0002 0 1 0 25.414062 25.414062 L 39 11.828125 L 39 20 A 2.0002 2.0002 0 1 0 43 20 L 43 7.2460938 A 2.0002 2.0002 0 0 0 40.960938 4.9804688 z M 12.5 8 C 8.3826878 8 5 11.382688 5 15.5 L 5 35.5 C 5 39.617312 8.3826878 43 12.5 43 L 32.5 43 C 36.617312 43 40 39.617312 40 35.5 L 40 26 A 2.0002 2.0002 0 1 0 36 26 L 36 35.5 C 36 37.446688 34.446688 39 32.5 39 L 12.5 39 C 10.553312 39 9 37.446688 9 35.5 L 9 15.5 C 9 13.553312 10.553312 12 12.5 12 L 22 12 A 2.0002 2.0002 0 1 0 22 8 L 12.5 8 z"></path>
- </svg>
- </div>
- </a>
- </section>
- </section>
- </main>
-
- <footer class="pt-10 p-5">
- <p class="text-xs opacity-70 mx-auto text-center">
- © 2023 GNU/Weeb.<br />Licensed under BSD 3-Clause License.
- </p>
- </footer>
-
- <script lang="text/javascript">
- const API_URL = "https://telegram-bot.teainside.org";
-
- function copyText() {
- var copyText = document.getElementById("copy-button");
- var text = document.getElementById("copy-text").innerText;
- navigator.clipboard.writeText(text);
- copyText.innerText = "Copied!";
- copyText.classList.add("bg-neutral-800");
- setTimeout(function () {
- copyText.innerText = "Copy";
- copyText.classList.remove("bg-neutral-800");
- }, 3000);
- }
-
- async function getOrgMembers() {
- const response = await fetch("https://api.github.com/orgs/gnuweeb/members");
- const data = await response.json();
-
- data.sort((left, right) => {
- const usernameA = left.login.toLowerCase();
- const usernameB = right.login.toLowerCase();
- if (usernameA < usernameB) return -1;
- if (usernameA > usernameB) return 1;
- return 0;
- });
-
- return data;
- }
-
- async function renderMemberList() {
- const membersData = await getOrgMembers();
- const memberList = document.getElementById("member-list");
-
- membersData.forEach(e => {
- const userAnchorEl = document.createElement("a");
- userAnchorEl.href = e.html_url;
- userAnchorEl.classList.add(
- "flex", "items-center", "space-x-3",
- "p-1", "rounded-lg", "hover:bg-neutral-800"
- );
-
- const userImgEl = document.createElement("img");
- userImgEl.src = e.avatar_url;
- userImgEl.alt = `${e.login} | Organization Member`;
- userImgEl.classList.add("rounded-full", "w-10");
-
- const usernameDivEl = document.createElement("div");
- usernameDivEl.classList.add("truncate", "text-sky-500");
- usernameDivEl.innerText = `@${e.login}`;
- userAnchorEl.appendChild(userImgEl);
- userAnchorEl.appendChild(usernameDivEl);
- memberList.appendChild(userAnchorEl);
- });
- }
-
- async function getRecentMessages() {
- try {
- const response = await fetch(API_URL + "/zxc.php?action=get_messages&chat_id=-1001483770714&limit=50");
- const { data } = (await response.json()).result;
-
- const transformedData = data.map(item => {
- return {
- user_id: item[0],
- username: item[1],
- first_name: item[2],
- last_name: item[3],
- user_photo: item[4],
- message_id: item[5],
- reply_to_message_id: item[6],
- message_type: item[7],
- text: item[8],
- text_entities: item[9] ? JSON.parse(item[9]) : null,
- file: item[10],
- date: item[11]
- };
- });
-
- return transformedData.reverse();
- } catch {
- return [];
- }
- }
-
- function hashCode(name) {
- var hash = 0;
- for (var i = 0; i < name.length; i++) {
- var character = name.charCodeAt(i);
- hash = ((hash << 5) - hash) + character;
- }
- return Math.abs(hash);
- }
-
- function getFixedRandomColor(name) {
- const colorData = {
- red: "text-red-400 border-red-400",
- yellow: "text-yellow-400 border-yellow-400",
- blue: "text-blue-400 border-blue-400",
- sky: "text-sky-400 border-sky-400",
- purple: "text-purple-400 border-purple-400",
- orange: "text-orange-400 border-orange-400",
- amber: "text-amber-400 border-amber-400",
- lime: "text-lime-400 border-lime-400",
- green: "text-green-400 border-green-400",
- emerald: "text-emerald-400 border-emerald-400",
- teal: "text-teal-400 border-teal-400",
- cyan: "text-cyan-400 border-cyan-400",
- indigo: "text-indigo-400 border-indigo-400",
- violet: "text-violet-400 border-violet-400",
- fuchsia: "text-fuchsia-400 border-fuchsia-400",
- pink: "text-pink-400 border-pink-400",
- rose: "text-rose-400 border-rose-400",
- };
- const colorNames = Object.keys(colorData);
- return colorData[colorNames[hashCode(name) % colorNames.length]].split(" ");
- }
-
- function cleanMessageText(text) {
- return text.replaceAll(/\n/g, " ");
- }
-
- function setupUserName(first, last) {
- const firstName = first.trimEnd();
- let lastName = "";
- if(last !== null) {
- lastName = " " + last.trimEnd();
- }
- return [ firstName, lastName ];
- }
-
- async function renderRecentMessages() {
- const messageData = await getRecentMessages();
- const recentMessages = document.getElementById("recent-messages");
-
- if (messageData.length === 0) {
- const connectionErrEl = document.createElement("div");
- connectionErrEl.classList.add("text-red-500", "italic", "text-center", "p-3");
- connectionErrEl.innerText = "Cannot Connect to the API.\nAPI Connection failure.";
- recentMessages.appendChild(connectionErrEl);
- return;
- }
-
- messageData.forEach(message => {
- const getColor = m => getFixedRandomColor(`${m.first_name}`);
-
- const chatContainer = document.createElement("div");
- chatContainer.id = message.message_id;
- chatContainer.classList.add("chat", "chat-start", "max-w-[300px]");
-
- const chatAvatar = document.createElement("div");
- chatAvatar.classList.add("chat-image", "avatar");
-
- const avatarRounded = document.createElement("div");
- avatarRounded.classList.add("w-10", "rounded-full");
-
- const avatarImg = document.createElement("img");
- avatarImg.setAttribute("draggable", "false");
- avatarImg.setAttribute("src", API_URL + "/storage/files/" + message.user_photo);
-
- avatarRounded.appendChild(avatarImg);
- chatAvatar.appendChild(avatarRounded);
-
- const chatBubble = document.createElement("div");
- chatBubble.id = `${message.message_id}-highlight`;
- chatBubble.classList.add(
- "chat-bubble", "transition", "before:transition",
- "duration-500", "before:duration-500", "ease-in-out",
- "before:ease-in-out", "delay-200", "before:delay-200"
- );
-
- const chatHeader = document.createElement("div");
- chatHeader.classList.add(
- "chat-header", "font-semibold", "pb-1",
- "line-clamp-1", getColor(message)[0],
- );
- const [ firstName, lastName ] = setupUserName(
- message.first_name,
- message.last_name
- );
- chatHeader.innerText = firstName + lastName;
-
- const chatMsgContent = document.createElement("div");
- if(message.message_type === "text") {
- chatMsgContent.classList.add(
- "text-neutral-300", "max-w-[150px]",
- "max-h-min", "line-clamp-2"
- );
- chatMsgContent.innerText = cleanMessageText(message.text);
- } else if(message.message_type === "photo") {
- const imageFile = API_URL + "/storage/files/" + message.file;
-
- const msgPhotoContainer = document.createElement("div");
- msgPhotoContainer.classList.add("relative");
-
- const messagePhoto = document.createElement("img");
- messagePhoto.src = imageFile;
- messagePhoto.classList.add("rounded-md", "mt-1", "relative");
-
- const hoverSeeImg = document.createElement("a");
- hoverSeeImg.href = imageFile;
- hoverSeeImg.setAttribute("target", "_blank");
- hoverSeeImg.setAttribute("draggable", "false");
- hoverSeeImg.classList.add(
- "absolute", "top-0", "w-full", "h-full", "flex", "rounded-md",
- "items-center", "justify-center", "hover:bg-neutral-900", "uppercase",
- "hover:bg-opacity-60", "transition", "duration-200", "ease-in-out",
- "font-bold", "text-xl", "text-white", "opacity-0", "hover:opacity-100",
- "select-none"
- );
- hoverSeeImg.innerText = "See";
-
- msgPhotoContainer.appendChild(messagePhoto);
- msgPhotoContainer.appendChild(hoverSeeImg);
- chatMsgContent.appendChild(msgPhotoContainer);
-
- if(message.text !== null) {
- const photoCaption = document.createElement("div");
- photoCaption.classList.add(
- "text-neutral-300", "line-clamp-2",
- "max-w-[150px]", "mt-2"
- );
- photoCaption.innerText = cleanMessageText(message.text);
- chatMsgContent.appendChild(photoCaption);
- }
- }
-
- const chatFooter = document.createElement("div");
- chatFooter.classList.add(
- "flex", "items-center", "pt-2",
- "justify-between", "space-x-3"
- );
-
- const readMore = document.createElement("a");
- readMore.setAttribute("href", "https://t.me/gnuweeb/" + message.message_id);
- readMore.setAttribute("draggable", "false");
- readMore.setAttribute("target", "_blank");
- readMore.classList.add(
- "text-xs", "text-sky-400", "opacity-70",
- "font-semibold", "select-none"
- );
- readMore.innerText = "Read more";
- chatFooter.appendChild(readMore);
-
- const chatDate = document.createElement("div");
- chatDate.classList.add(
- "flex", "justify-end", "space-x-1",
- "text-xs", "opacity-70",
- );
-
- const msgTime = document.createElement("time");
- msgTime.innerText = message.date;
-
- chatDate.appendChild(msgTime);
-
- chatFooter.appendChild(chatDate);
-
- chatBubble.appendChild(chatHeader);
-
- const replyMessages = messageData.filter(msg => {
- return msg.message_id === message.reply_to_message_id
- });
- if(message.reply_to_message_id !== null && replyMessages.length > 0) {
- const replyMessage = replyMessages[0];
-
- const chatMsgReply = document.createElement("button");
- chatMsgReply.onclick = () => {
- const targetReply = document.getElementById(message.reply_to_message_id.toString());
- const highlightReply = document.getElementById(`${message.reply_to_message_id}-highlight`);
-
- targetReply.scrollIntoView({
- behavior: "smooth", block: "end", inline: "nearest"
- });
-
- highlightReply.classList.add(
- "!bg-neutral-700", "!scale-105"
- );
-
- setTimeout(() => {
- highlightReply.classList.remove(
- "!bg-neutral-700", "!scale-105"
- );
- }, 2000);
- }
- chatMsgReply.classList.add(
- "w-full", "border-l-2", "!my-2", "text-sm", "text-start",
- "pl-2", "py-1", getColor(replyMessage)[1], "flex", "flex-col",
- "text-neutral-300", "text-opacity-80", "hover:bg-neutral-800",
- "rounded-r-md", "rounded-l-sm"
- );
-
- const usernameMsgReply = document.createElement("span");
- usernameMsgReply.classList.add(
- "not-italic", "font-semibold", "line-clamp-1",
- "select-none", getColor(replyMessage)[0]
- );
- const [ firstName, lastName ] = setupUserName(
- replyMessage.first_name,
- replyMessage.last_name
- );
- usernameMsgReply.innerText = firstName + lastName;
-
- const textMsgReply = document.createElement("span");
- textMsgReply.classList.add(
- "line-clamp-1", "max-w-[150px]",
- "max-h-min", "text-start"
- );
- textMsgReply.innerText = cleanMessageText(
- replyMessage.text !== null ? replyMessage.text : "Photo"
- );
-
- chatMsgReply.appendChild(usernameMsgReply);
- chatMsgReply.appendChild(textMsgReply);
- chatBubble.appendChild(chatMsgReply);
- };
-
- chatBubble.appendChild(chatMsgContent);
- chatBubble.appendChild(chatFooter);
-
- chatContainer.appendChild(chatAvatar);
- chatContainer.appendChild(chatBubble);
-
- recentMessages.appendChild(chatContainer);
- });
-
- recentMessages.lastChild.scrollIntoView({
- behavior: "instant", block: "end", inline: "nearest"
- });
- };
-
- document.addEventListener("DOMContentLoaded", function() {
- renderMemberList();
- renderRecentMessages();
- });
- </script>
-
- </body>
-
-</html>
diff --git a/style.css b/style.css
deleted file mode 100644
index 19d1659..0000000
--- a/style.css
+++ /dev/null
@@ -1,57 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-
-.chat {
- @apply grid gap-x-3 py-1
-}
-
-.chat-start {
- @apply place-items-start grid-cols-[auto,1fr];
-}
-
-.chat-image {
- @apply row-span-2 self-end;
-}
-
-.chat-start .chat-image {
- @apply col-start-1;
-}
-
-.chat-start .chat-header {
- @apply col-start-2;
-}
-
-.chat-bubble {
- @apply relative block w-fit px-4 py-2 max-w-[90%] rounded-2xl
- min-h-[2.75rem] min-w-[2.75rem] bg-neutral-900 text-neutral-500;
-}
-
-.chat-bubble::before {
- @apply absolute bottom-0 h-3 w-3 bg-inherit content-[""];
- mask-size: contain;
- -webkit-mask-size: contain;
- mask-repeat: no-repeat;
- -webkit-mask-repeat: no-repeat;
- mask-position: center;
- -webkit-mask-position: center;
-}
-
-.chat-start .chat-bubble {
- @apply col-start-2 rounded-bl-none;
-}
-
-.chat-start .chat-bubble::before {
- @apply content-[""] -left-3;
- mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
- -webkit-mask-image: url("data:image/svg+xml,%3csvg width='3' height='3' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='m 0 3 L 3 3 L 3 0 C 3 1 1 3 0 3'/%3e%3c/svg%3e");
-}
-
-.avatar {
- @apply relative inline-flex;
-}
-
-.avatar > div {
- @apply block aspect-square overflow-hidden;
-}
--
Muhammad Rizki
^ permalink raw reply related [flat|nested] 16+ messages in thread