diff --git a/README.md b/README.md index 0f7973004..c12e343ca 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,61 @@ We are a research lab working with the goal of using data, tech, design and soci Prerequisites: NodeJS must be installed on your machine. 1. Clone this repo. -2. Run `npm start` command inside the root folder of the project. -3. To build the website, run `npm run build`. -4. To run the local build, run the following command: `npm run serve`. +2. Run `npm install --legacy-peer-deps` to install dependencies. +3. Run `npm start` to start the development server at `http://localhost:8000`. +4. To build the website, run `npm run build`. +5. To run the local build, run the following command: `npm run serve`. + +## Content Management (Decap CMS) + +The website uses [Decap CMS](https://decapcms.org/) for managing content through a UI without editing markdown files directly. + +### Running the CMS locally + +1. Start the Gatsby dev server: `npm start` +2. In a separate terminal, start the Decap proxy server: `npx decap-server` +3. Open `http://localhost:8000/admin/index.html` in your browser +4. Click **Login** — no GitHub auth needed locally, it connects directly to your local files + +### Accessing the CMS in production + +Visit `https://civicdatalab.in/admin/` and log in with your GitHub account. + +> You must have **Write** access to the `CivicDataLab/civicdatalab.github.io` repo to save content. + +### Giving someone CMS access + +1. Go to the repo on GitHub → **Settings → Collaborators and teams** +2. Add the person's GitHub account with **Write** access +3. They can now log into the CMS using their GitHub account + +### Setting up the GitHub OAuth App (one-time, for production) + +1. Go to **GitHub → Settings → Developer settings → OAuth Apps → New OAuth App** +2. Set **Homepage URL** to `https://civicdatalab.in` +3. Set **Authorization callback URL** to `https://civicdatalab.in/admin/` +4. Copy the **Client ID** and update `app_id` in `static/admin/config.yml` + +### Admin portal branding + +The CMS login page (`/admin/`) has been customised: +- **Splash screen** — a full-page branded loading screen with the CivicDataLab logo (`/static/cdl_logo.png`) is shown while the CMS loads, then fades out. +- **Login page logo** — the default Decap logo is replaced with the CivicDataLab logo via the `logo_url` field in `static/admin/config.yml`. +- **Decap footer** — the Decap attribution SVG at the bottom of the login page is hidden via a `MutationObserver` in `static/admin/index.html`. + +To update the logo, replace `/static/cdl_logo.png` and update the `logo_url` in `static/admin/config.yml` if the path changes. + +### CMS collections available + +| Collection | Content folder | +|---|---| +| Team Members | `content/team/` | +| Alumni | `content/alumnus/` | +| Work (by sector) | `content/work/` | +| Events | `content/events/` | +| Job Openings | `content/openings/` | +| Values | `content/values/` | +| Project Partners | `content/projectpart/` | ## Wiki You can find guides on how to add/update project and bandhu level info [here](https://github.com/CivicDataLab/civicdatalab.github.io/wiki). diff --git a/package-lock.json b/package-lock.json index 3d0ce98b8..771cd78d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "react-dom": "^16.12.0", "react-helmet": "^5.2.1", "react-icons": "^4.1.0", + "react-is": "^16.13.1", "react-multi-carousel": "^2.6.2", "react-reveal": "^1.2.2", "react-select": "^5.7.4", @@ -45,6 +46,7 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2409,6 +2411,7 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -2803,6 +2806,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -2815,7 +2819,8 @@ "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true }, "node_modules/@iarna/toml": { "version": "2.2.5", @@ -4322,6 +4327,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, "engines": { "node": ">=6" } @@ -4779,6 +4785,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, "engines": { "node": ">=8" } @@ -9274,6 +9281,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -9539,6 +9547,7 @@ "version": "7.32.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, "dependencies": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -9860,6 +9869,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, "engines": { "node": ">=10" } @@ -9868,6 +9878,7 @@ "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, "dependencies": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -9881,6 +9892,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, "engines": { "node": ">=4" } @@ -10536,6 +10548,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -10753,6 +10766,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -10765,7 +10779,8 @@ "node_modules/flatted": { "version": "3.2.9", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==" + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true }, "node_modules/flush-write-stream": { "version": "1.1.1", @@ -13495,6 +13510,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -13509,6 +13525,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, "engines": { "node": ">=10" }, @@ -14225,11 +14242,6 @@ "react-is": "^16.7.0" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -16309,6 +16321,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -16519,7 +16532,8 @@ "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true }, "node_modules/lodash.template": { "version": "4.5.0", @@ -16541,7 +16555,8 @@ "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true }, "node_modules/lodash.uniq": { "version": "4.5.0", @@ -19021,6 +19036,7 @@ "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", @@ -20988,6 +21004,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -21048,11 +21065,6 @@ "node": ">= 8.3" } }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/probe-image-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-6.0.0.tgz", @@ -21111,11 +21123,6 @@ "react-is": "^16.13.1" } }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/proper-lockfile": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", @@ -21654,10 +21661,9 @@ } }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "peer": true + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", @@ -22772,6 +22778,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -23991,6 +23998,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -24007,6 +24015,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -25281,6 +25290,7 @@ "version": "6.8.1", "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -25296,6 +25306,7 @@ "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -25310,12 +25321,14 @@ "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -25323,12 +25336,14 @@ "node_modules/table/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "node_modules/table/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -25900,6 +25915,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -25907,20 +25923,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "license": "(MIT OR CC0-1.0)", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -26012,19 +26014,6 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", diff --git a/package.json b/package.json index ef2a6f316..660539d09 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "react-dom": "^16.12.0", "react-helmet": "^5.2.1", "react-icons": "^4.1.0", + "react-is": "^16.13.1", "react-multi-carousel": "^2.6.2", "react-reveal": "^1.2.2", "react-select": "^5.7.4", diff --git a/static/admin/config.yml b/static/admin/config.yml new file mode 100644 index 000000000..cbbe8e7c5 --- /dev/null +++ b/static/admin/config.yml @@ -0,0 +1,359 @@ +backend: + name: github + repo: CivicDataLab/civicdatalab.github.io + branch: main + auth_type: pkce + app_id: YOUR_GITHUB_OAUTH_APP_CLIENT_ID # TODO: Create a GitHub OAuth App and replace this before merging to main + +logo_url: /cdl_logo.png + +media_folder: "static/images/uploads" +public_folder: "/images/uploads" + +slug: + encoding: "ascii" + clean_accents: true + +collections: + + # ─── TEAM MEMBERS ─────────────────────────────────────────────────────────── + - label: "Team Members" + name: "team" + folder: "content/team" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}} — {{role}}" + fields: + - { label: "Full Name", name: "name", widget: "string" } + - { label: "Role / Title", name: "role", widget: "string" } + - { label: "Description", name: "description", widget: "text", required: false } + - { label: "Quote", name: "quote", widget: "string", required: false } + - { label: "Profile Image", name: "image", widget: "image", required: false } + - { label: "GitHub URL", name: "github", widget: "string", required: false } + - { label: "Twitter URL", name: "twitter", widget: "string", required: false } + - { label: "LinkedIn URL", name: "linkedin", widget: "string", required: false } + - { label: "Medium URL", name: "medium", widget: "string", required: false } + - { label: "Accent Color", name: "accentcolor", widget: "string", required: false } + - { label: "Sectors", name: "sectors", widget: "string", required: false, hint: "Comma-separated. e.g. Public Finance, Climate Action" } + - { label: "Projects", name: "projects", widget: "string", required: false, hint: "Comma-separated project names" } + - { label: "Bio (body text)", name: "body", widget: "markdown", required: false } + + # ─── ALUMNI ───────────────────────────────────────────────────────────────── + - label: "Alumni" + name: "alumnus" + folder: "content/alumnus" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}} — {{role}}" + fields: + - { label: "Full Name", name: "name", widget: "string" } + - { label: "Role / Title", name: "role", widget: "string", required: false } + - { label: "Description", name: "description", widget: "text", required: false } + - { label: "Quote", name: "quote", widget: "string", required: false } + - { label: "Profile Image", name: "image", widget: "image", required: false } + - { label: "GitHub URL", name: "github", widget: "string", required: false } + - { label: "Twitter URL", name: "twitter", widget: "string", required: false } + - { label: "LinkedIn URL", name: "linkedin", widget: "string", required: false } + - { label: "Medium URL", name: "medium", widget: "string", required: false } + - { label: "Accent Color", name: "accentcolor", widget: "string", required: false } + - { label: "Sectors", name: "sectors", widget: "string", required: false } + - { label: "Projects", name: "projects", widget: "string", required: false } + - { label: "Bio (body text)", name: "body", widget: "markdown", required: false } + + # ─── PROJECT PARTNERS ─────────────────────────────────────────────────────── + - label: "Project Partners" + name: "projectpart" + folder: "content/projectpart" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}}" + fields: + - { label: "Organisation Name", name: "name", widget: "string" } + - { label: "Short Name / Acronym", name: "short", widget: "string", required: false } + - { label: "Logo", name: "logo", widget: "image", required: false } + - { label: "Testimonial", name: "testimonial", widget: "text", required: false } + - { label: "Website", name: "website", widget: "string", required: false } + - { label: "Sectors", name: "sectors", widget: "string", required: false } + - { label: "Projects", name: "projects", widget: "string", required: false } + + # ─── VALUES ───────────────────────────────────────────────────────────────── + - label: "Values" + name: "values" + folder: "content/values" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: title + summary: "{{number}}. {{title}}" + fields: + - { label: "Number", name: "number", widget: "string", required: false, hint: "e.g. 01, 02 ..." } + - { label: "Title", name: "title", widget: "string" } + - { label: "Image", name: "image", widget: "image", required: false } + - { label: "Description", name: "body", widget: "markdown", required: false } + + # ─── JOB OPENINGS ─────────────────────────────────────────────────────────── + - label: "Job Openings" + name: "openings" + folder: "content/openings" + create: true + format: frontmatter + extension: md + identifier_field: title + summary: "{{title}}" + fields: + - { label: "Job Title", name: "title", widget: "string" } + - { label: "Application URL", name: "url", widget: "string" } + + # ─── WORK: PUBLIC FINANCE ──────────────────────────────────────────────────── + - label: "Work: Public Finance" + name: "work_publicfinance" + folder: "content/work/publicfinance" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}}" + filter: { field: "type", value: "project" } + fields: + - { label: "Project Name", name: "name", widget: "string" } + - { label: "Summary", name: "summary", widget: "text", required: false } + - { label: "Context", name: "context", widget: "text", required: false } + - { label: "Solution", name: "solution", widget: "text", required: false } + - { label: "Image", name: "image", widget: "image", required: false } + - { label: "Website URL", name: "url", widget: "string", required: false } + - { label: "Twitter", name: "twitter", widget: "string", required: false } + - { label: "GitHub", name: "github", widget: "string", required: false } + - { label: "Facebook", name: "facebook", widget: "string", required: false } + - { label: "LinkedIn", name: "linkedin", widget: "string", required: false } + - { label: "Sector", name: "sector", widget: "hidden", default: "Public Finance" } + - { label: "Type", name: "type", widget: "hidden", default: "project" } + - label: "Resources" + name: "resources" + widget: "list" + required: false + fields: + - { label: "Title", name: "title", widget: "string" } + - { label: "Link", name: "link", widget: "string" } + - { label: "Type", name: "type", widget: "select", options: ["Blog", "Report", "Dashboard", "Video", "Forum", "Tutorial", "Doc"] } + + # ─── WORK: CLIMATE ACTION ──────────────────────────────────────────────────── + - label: "Work: Climate Action" + name: "work_climateaction" + folder: "content/work/climateaction" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}}" + filter: { field: "type", value: "project" } + fields: + - { label: "Project Name", name: "name", widget: "string" } + - { label: "Summary", name: "summary", widget: "text", required: false } + - { label: "Context", name: "context", widget: "text", required: false } + - { label: "Solution", name: "solution", widget: "text", required: false } + - { label: "Image", name: "image", widget: "image", required: false } + - { label: "Website URL", name: "url", widget: "string", required: false } + - { label: "Twitter", name: "twitter", widget: "string", required: false } + - { label: "GitHub", name: "github", widget: "string", required: false } + - { label: "Sector", name: "sector", widget: "hidden", default: "Climate Action" } + - { label: "Type", name: "type", widget: "hidden", default: "project" } + - label: "Resources" + name: "resources" + widget: "list" + required: false + fields: + - { label: "Title", name: "title", widget: "string" } + - { label: "Link", name: "link", widget: "string" } + - { label: "Type", name: "type", widget: "select", options: ["Blog", "Report", "Dashboard", "Video", "Forum", "Tutorial", "Doc"] } + + # ─── WORK: LAW & JUSTICE ───────────────────────────────────────────────────── + - label: "Work: Law & Justice" + name: "work_lawandjustice" + folder: "content/work/lawandjustice" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}}" + filter: { field: "type", value: "project" } + fields: + - { label: "Project Name", name: "name", widget: "string" } + - { label: "Summary", name: "summary", widget: "text", required: false } + - { label: "Context", name: "context", widget: "text", required: false } + - { label: "Solution", name: "solution", widget: "text", required: false } + - { label: "Image", name: "image", widget: "image", required: false } + - { label: "Website URL", name: "url", widget: "string", required: false } + - { label: "Twitter", name: "twitter", widget: "string", required: false } + - { label: "GitHub", name: "github", widget: "string", required: false } + - { label: "Sector", name: "sector", widget: "hidden", default: "Law & Justice" } + - { label: "Type", name: "type", widget: "hidden", default: "project" } + - label: "Resources" + name: "resources" + widget: "list" + required: false + fields: + - { label: "Title", name: "title", widget: "string" } + - { label: "Link", name: "link", widget: "string" } + - { label: "Type", name: "type", widget: "select", options: ["Blog", "Report", "Dashboard", "Video", "Forum", "Tutorial", "Doc"] } + + # ─── WORK: OPEN CONTRACTING ────────────────────────────────────────────────── + - label: "Work: Open Contracting" + name: "work_opencontracting" + folder: "content/work/opencontracting" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}}" + filter: { field: "type", value: "project" } + fields: + - { label: "Project Name", name: "name", widget: "string" } + - { label: "Summary", name: "summary", widget: "text", required: false } + - { label: "Context", name: "context", widget: "text", required: false } + - { label: "Solution", name: "solution", widget: "text", required: false } + - { label: "Image", name: "image", widget: "image", required: false } + - { label: "Website URL", name: "url", widget: "string", required: false } + - { label: "Twitter", name: "twitter", widget: "string", required: false } + - { label: "GitHub", name: "github", widget: "string", required: false } + - { label: "Sector", name: "sector", widget: "hidden", default: "Open Contracting" } + - { label: "Type", name: "type", widget: "hidden", default: "project" } + - label: "Resources" + name: "resources" + widget: "list" + required: false + fields: + - { label: "Title", name: "title", widget: "string" } + - { label: "Link", name: "link", widget: "string" } + - { label: "Type", name: "type", widget: "select", options: ["Blog", "Report", "Dashboard", "Video", "Forum", "Tutorial", "Doc"] } + + # ─── WORK: DIGITAL PUBLIC GOODS ────────────────────────────────────────────── + - label: "Work: Digital Public Goods" + name: "work_dpg" + folder: "content/work/dpg" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}}" + filter: { field: "type", value: "project" } + fields: + - { label: "Project Name", name: "name", widget: "string" } + - { label: "Summary", name: "summary", widget: "text", required: false } + - { label: "Context", name: "context", widget: "text", required: false } + - { label: "Solution", name: "solution", widget: "text", required: false } + - { label: "Image", name: "image", widget: "image", required: false } + - { label: "Website URL", name: "url", widget: "string", required: false } + - { label: "GitHub", name: "github", widget: "string", required: false } + - { label: "Sector", name: "sector", widget: "hidden", default: "Digital Public Goods" } + - { label: "Type", name: "type", widget: "hidden", default: "project" } + - label: "Resources" + name: "resources" + widget: "list" + required: false + fields: + - { label: "Title", name: "title", widget: "string" } + - { label: "Link", name: "link", widget: "string" } + - { label: "Type", name: "type", widget: "select", options: ["Blog", "Report", "Dashboard", "Video", "Forum", "Tutorial", "Doc"] } + + # ─── WORK: URBAN DEVELOPMENT ───────────────────────────────────────────────── + - label: "Work: Urban Development" + name: "work_urbandevelopment" + folder: "content/work/urbandevelopment" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}}" + filter: { field: "type", value: "project" } + fields: + - { label: "Project Name", name: "name", widget: "string" } + - { label: "Summary", name: "summary", widget: "text", required: false } + - { label: "Context", name: "context", widget: "text", required: false } + - { label: "Solution", name: "solution", widget: "text", required: false } + - { label: "Image", name: "image", widget: "image", required: false } + - { label: "Website URL", name: "url", widget: "string", required: false } + - { label: "GitHub", name: "github", widget: "string", required: false } + - { label: "Sector", name: "sector", widget: "hidden", default: "Urban Development" } + - { label: "Type", name: "type", widget: "hidden", default: "project" } + - label: "Resources" + name: "resources" + widget: "list" + required: false + fields: + - { label: "Title", name: "title", widget: "string" } + - { label: "Link", name: "link", widget: "string" } + - { label: "Type", name: "type", widget: "select", options: ["Blog", "Report", "Dashboard", "Video", "Forum", "Tutorial", "Doc"] } + + # ─── EVENTS: DATA DIALOGUES ────────────────────────────────────────────────── + - label: "Events: Data Dialogues" + name: "events_datadialogues" + folder: "content/events/data-dialogues" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}}" + filter: { field: "type", value: "eventdetail" } + fields: + - { label: "Event Name", name: "name", widget: "string" } + - { label: "Summary", name: "summary", widget: "text", required: false } + - { label: "Context", name: "context", widget: "text", required: false } + - { label: "Event Type", name: "eventtype", widget: "hidden", default: "Data Dialogues" } + - { label: "Banner Image", name: "image", widget: "image", required: false } + - { label: "Report URL", name: "url", widget: "string", required: false } + - { label: "YouTube URL", name: "youtube", widget: "string", required: false } + - { label: "Type", name: "type", widget: "hidden", default: "eventdetail" } + - label: "Resources" + name: "resources" + widget: "list" + required: false + fields: + - { label: "Title", name: "title", widget: "string" } + - { label: "Link", name: "link", widget: "string" } + - { label: "Type", name: "type", widget: "select", options: ["Doc", "Video", "Blog", "Report"] } + + # ─── EVENTS: CLIMATE DIALOGUES ─────────────────────────────────────────────── + - label: "Events: Climate Dialogues" + name: "events_climatedialogues" + folder: "content/events/climate-dialogues" + path: "{{slug}}/index" + create: true + format: frontmatter + extension: md + identifier_field: name + summary: "{{name}}" + filter: { field: "type", value: "eventdetail" } + fields: + - { label: "Event Name", name: "name", widget: "string" } + - { label: "Summary", name: "summary", widget: "text", required: false } + - { label: "Context", name: "context", widget: "text", required: false } + - { label: "Event Type", name: "eventtype", widget: "hidden", default: "Climate Dialogues" } + - { label: "Banner Image", name: "image", widget: "image", required: false } + - { label: "Report URL", name: "url", widget: "string", required: false } + - { label: "YouTube URL", name: "youtube", widget: "string", required: false } + - { label: "Type", name: "type", widget: "hidden", default: "eventdetail" } + - label: "Resources" + name: "resources" + widget: "list" + required: false + fields: + - { label: "Title", name: "title", widget: "string" } + - { label: "Link", name: "link", widget: "string" } + - { label: "Type", name: "type", widget: "select", options: ["Doc", "Video", "Blog", "Report"] } diff --git a/static/admin/index.html b/static/admin/index.html new file mode 100644 index 000000000..57a93f4ad --- /dev/null +++ b/static/admin/index.html @@ -0,0 +1,55 @@ + + + + + + CivicDataLab | Content Manager + + + +
+ CivicDataLab +

Loading Content Manager...

+
+ + + +