diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a5652412..d0bddc76 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,7 +1,7 @@ on: push: branches: - - main + - cd-bund jobs: deploy: @@ -17,12 +17,9 @@ jobs: - run: npm ci - run: npm run build env: - DEFAULT_COUNTRY_SECTION: italy - ELASTIC_URL: "https://elasticsearch.developers.italia.it/indicepa_pec/_search" + DEFAULT_COUNTRY_SECTION: switzerland - run: | - git remote set-url origin https://git:${GITHUB_TOKEN}@github.com/italia/publiccode-editor.git - echo publiccode-editor.developers.italia.it > dist/CNAME - - npm run deploy -m "Automated deployment: ${CIRCLE_SHA1} [ci skip]" + git remote set-url origin https://git:${GITHUB_TOKEN}@github.com/swiss/publiccode-editor.git + npm run gdeploy -m "Automated deployment: ${CIRCLE_SHA1} [ci skip]" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publiccode-validation.yml b/.github/workflows/publiccode-validation.yml index 398c42c4..4c2d91c8 100644 --- a/.github/workflows/publiccode-validation.yml +++ b/.github/workflows/publiccode-validation.yml @@ -5,6 +5,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: italia/publiccode-parser-action@v1.3.3 + - uses: italia/publiccode-parser-action@v1.4.2 with: publiccode: 'publiccode.yml' diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..ec1ef44f --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @olibrian \ No newline at end of file diff --git a/README.md b/README.md index 0245b9f0..0a904e17 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,19 @@ # publiccode yml Editor + +This project is a fork of [italia/publiccode-editor](https://github.com/italia/publiccode-editor), customized to align with the Design System of the Swiss Confederation 🇨🇭. + +For details about the Swiss Design System, see: + +- [Design System for the Swiss Confederation (GitHub)](https://github.com/swiss/designsystem) +- [Design System for the Swiss Confederation (Stoybook)](https://swiss.github.io/designsystem/?path=/docs/get-started--docs) +- [Design System Core Library (Figma)](https://www.figma.com/design/3UYgqxmcJbG0hpWuti3y8U/🇨🇭Design-System-Core-Library) + +The application is live at: https://swiss.github.io/publiccode-editor/ + +Below is the original README for the Italian version. + +--- + ![Build Status](https://img.shields.io/circleci/project/github/italia/publiccode-editor/master.svg) ![Issues](https://img.shields.io/github/issues/italia/publiccode-editor.svg) ![License](https://img.shields.io/github/license/italia/publiccode-editor.svg) [![Join the #publiccode channel](https://img.shields.io/badge/Slack%20channel-%23publiccode-blue.svg?logo=slack)](https://developersitalia.slack.com/messages/CAM3F785T) [![Get invited](https://slack.developers.italia.it/badge.svg)](https://slack.developers.italia.it/) diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..091882a0 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,37 @@ +# RELEASE + +The release process is automated using Github Actions. This automated process mirrors the manual one currently used. + +## Branch workflow + +### Start a release + +Everytime a new release starts, you have to run the action *create-release-pr*. +It will ask if you wanna relase a patch, a minor or a major. +After that, it will: + +- Generate a new version of the package +- Create a branch with this name release/*\* starting from *develop* +- It will update the *package.json* +- It will update the *publiccode.yml* +- It will open a PR on that branch + +The PR process has the aim of giving the freedom to do manual editing. +You MUST update *CHANGELOG.md* manually before closing the PR. + +### Finishing a release + +Another Github Action, *finish-release*, is triggered when the PR is closed on *main*. + +This action will: + +- Create a tag and push it +- Merge *main* on *develop* +- Create a *release package* on Github + +It's highly recommended to edit manually the description of the release. +It will be automated in the next releases. + +## Future enhancements + +This worfklow will be changed with the adoption of more solid and more robust solutions. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d1957a2a..24062242 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,12 +7,13 @@ "": { "name": "publiccode-editor", "version": "2.1.1", + "hasInstallScript": true, "license": "AGPL-3.0-or-later", "dependencies": { "@uiw/react-md-editor": "^4.0.5", "accessible-autocomplete": "^3.0.1", "bootstrap": "^5.3.6", - "bootstrap-italia": "^2.14.0", + "bootstrap-switzerland": "swiss/bootstrap-switzerland#gh-pages", "copy-to-clipboard": "^3.3.3", "countries-list": "^3.0.6", "date-fns": "^4.1.0", @@ -5583,6 +5584,24 @@ "resolved": "https://registry.npmjs.org/bootstrap-italia/-/bootstrap-italia-2.14.0.tgz", "integrity": "sha512-df8zE55x6FIViPxVXjfggaJVoR/9DMKR37dpvgs/Y6pwc8kKU8ShPEusnr2kyy4w5pQvBeuKmsBT+dltkXy9rA==", "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@popperjs/core": "^2.11.6", + "@splidejs/splide": "^4.1.4", + "@types/bootstrap": "^5.2.6", + "animejs": "^3.2.1", + "design-tokens-italia": "^1.1.1", + "just-validate": "^4.3.0", + "minimasonry": "^1.3.2", + "progressbar.js": "^1.1.0", + "uuid": "^8.3.2", + "video.js": "^8.21.0" + } + }, + "node_modules/bootstrap-switzerland": { + "version": "2.16.2", + "resolved": "git+ssh://git@github.com/swiss/bootstrap-switzerland.git#39349792d85f647c868d255d4f3e4b586f8946a7", + "license": "BSD-3-Clause", "dependencies": { "@popperjs/core": "^2.11.6", "@splidejs/splide": "^4.1.4", diff --git a/package.json b/package.json index e497a213..ad60bee3 100644 --- a/package.json +++ b/package.json @@ -13,12 +13,15 @@ "prebuild": "npm run build:wasm && npm run build:licenses", "build:providers-oembed": "tsx scripts/getProvidersOembed.ts src/generated/providers-oembed.json", "build:licenses": "mkdir -p src/generated && tsx scripts/genLicenseList.ts src/generated/licenses.json", + "build:organisations": "tsx src/app/data/generateOrganisations.ts", "build:wasm": "cp \"$(go env GOROOT)/misc/wasm/wasm_exec.js\" public && GOOS=js GOARCH=wasm go build -o public/main.wasm src/wasm/main.go", "serve": "rm -rf dist; npm run build && http-server dist", "format": "prettier --write 'src/**/*.{ts,tsx,scss,css,json}' ", "test": "jest --passWithNoTests", + "gdeploy": "gh-pages -u 'Deploy Bot ' -d dist", "deploy": "gh-pages -u 'Deploy Bot ' -d dist", "release": "release-it", + "postinstall": "npm run build:organisations", "_postinstall": "patch-package" }, "keywords": [ @@ -28,7 +31,7 @@ ], "repository": { "type": "git", - "url": "git@github.com:italia/publiccode-editor.git" + "url": "git@github.com:swiss/publiccode-editor.git" }, "jest": { "moduleNameMapper": { @@ -43,7 +46,7 @@ "@uiw/react-md-editor": "^4.0.5", "accessible-autocomplete": "^3.0.1", "bootstrap": "^5.3.6", - "bootstrap-italia": "^2.14.0", + "bootstrap-switzerland": "swiss/bootstrap-switzerland#gh-pages", "copy-to-clipboard": "^3.3.3", "countries-list": "^3.0.6", "date-fns": "^4.1.0", diff --git a/public/assets/img/favicon-32x32.png b/public/assets/img/favicon-32x32.png index 56b1cac7..11f10c46 100644 Binary files a/public/assets/img/favicon-32x32.png and b/public/assets/img/favicon-32x32.png differ diff --git a/publiccode.yml b/publiccode.yml index 8d0f2302..3663103b 100644 --- a/publiccode.yml +++ b/publiccode.yml @@ -1,69 +1,54 @@ -publiccodeYmlVersion: "0.3" +publiccodeYmlVersion: 0.5.0 +name: Publiccode Editor +url: https://github.com/swiss/publiccode-editor +softwareVersion: 2.1.0 +releaseDate: 2025-07-03 +platforms: + - web categories: - - it-development + - application-development +developmentStatus: development +softwareType: standalone/web +organisation: + uri: https://ld.admin.ch/FCh + name: Bundeskanzlei description: - it: - features: - - Generazione di publiccode.yml - - Modifica di publiccode.yml - - Validazione di publiccode.yml - - Importazione di publiccode.yml tramite URL - - Possibilità di gestire diverse lingue - genericName: Generatore di publiccode.yml - longDescription: > - publiccode editor è un'applicazione web per generare file - - [`publiccode.yml`](https://github.com/italia/publiccode.yml) validi. - - Compilando il form, genera automaticamente un file YAML compatible con + de-CH: + localisedName: publiccode.yml Editor + shortDescription: Ein Web-Editor zur Erstellung und Validierung von publiccode.yml-Dateien. + longDescription: >- + Der PublicCode-Editor ist eine Webanwendung zur Erstellung gültiger + publiccode.yml-Dateien. - l'ultima versione dello standard publiccode. Questo file può essere - copiato - o scaricato localmente per essere poi inserito nel repository di - destinazione. + Basierend auf den Angaben im Formular wird eine YAML-Datei generiert, die + dem neuesten PublicCode-Standard entspricht. Die Datei kann direkt kopiert + oder heruntergeladen und in ein Repository übernommen werden. - - Può inoltre essere usato come validatore. È possible incollare o importare - - un file `publiccode.yml` esistente all'interno dell'editor. L'editor - validerà - - il documento importato e aiuterà a correggere eventuali errori. - shortDescription: Un editor web per generare e validare file publiccode.yml. + Der Editor kann auch zur Validierung bestehender publiccode.yml-Dateien + verwendet werden. + features: + - Generierung von publiccode.yml + - Modifikation von publiccode.yml + - Validierung von publiccode.yml + - Import von publiccode.yml über URL + - Mehrere Sprachen können verwaltet werden screenshots: - screenshot.png -developmentStatus: stable -it: - countryExtensionVersion: "0.2" - piattaforme: - anpr: false - cie: false - pagopa: false - spid: false - riuso: - codiceIPA: pcm legal: license: AGPL-3.0-or-later - authorsFile: AUTHORS.md +maintenance: + type: community + contacts: + - name: Olivier Brian + email: brian@puzzle.ch + - name: Claudia Asti + email: asti@puzzle.ch localisation: + localisationReady: true availableLanguages: - de - en - fr - it - nl - localisationReady: true -maintenance: - contacts: - - name: Leonardo Favario - - name: Alessandro Sebastiani - - name: Fabio Bonelli - type: community -name: publiccode editor -platforms: - - web -releaseDate: 2025-07-23 -softwareType: standalone/web -softwareVersion: 2.1.1 -url: https://github.com/italia/publiccode-editor diff --git a/screenshot.png b/screenshot.png index cff9c1be..d945dce5 100644 Binary files a/screenshot.png and b/screenshot.png differ diff --git a/src/app/App.tsx b/src/app/App.tsx index b8c7ea38..3a604c3c 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -1,4 +1,4 @@ -import "bootstrap-italia/dist/css/bootstrap-italia.min.css"; +import "bootstrap-switzerland/dist/css/bootstrap-switzerland.min.css"; import { NotificationManager } from "design-react-kit"; import { useState } from "react"; import { useTranslation } from "react-i18next"; diff --git a/src/app/components/Editor.tsx b/src/app/components/Editor.tsx index 1267d62b..8b1fce3e 100644 --- a/src/app/components/Editor.tsx +++ b/src/app/components/Editor.tsx @@ -12,7 +12,8 @@ import useFormPersist from "react-hook-form-persist"; import { useTranslation } from "react-i18next"; import { RequiredDeep } from "type-fest"; import licenses from "../../generated/licenses.json"; -import { allLangs, displayName } from "../../i18n"; +import organisationData from "../data/organisations.json"; +import { allLangs, displayName, getLocalizedText } from "../../i18n"; import categories from "../contents/categories"; import { DEFAULT_COUNTRY_SECTIONS } from "../contents/constants"; import * as countrySection from "../contents/countrySpecificSection"; @@ -21,7 +22,6 @@ import maintenanceTypes from "../contents/maintenanceTypes"; import mimeTypes from "../contents/mime-types"; import platforms from "../contents/platforms"; import PublicCode, { - defaultItaly, IT_COUNTRY_EXTENSION_VERSION, LATEST_VERSION, PublicCodeWithDeprecatedFields, @@ -128,12 +128,13 @@ const resolver: Resolver = async ( const defaultValues = { publiccodeYmlVersion: LATEST_VERSION, legal: {}, + organisation: {}, localisation: { availableLanguages: [] }, maintenance: { contacts: undefined, contractors: undefined }, platforms: [], categories: undefined, description: {}, - it: defaultItaly, + it: undefined }; const isNotTheSameVersion = (version1: string, version2: string) => { @@ -147,7 +148,7 @@ const isNotTheSameVersion = (version1: string, version2: string) => { export default function Editor() { //#region UI - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const { countrySections } = useCountryStore(); const { resetWarnings, setWarnings } = useWarningStore(); const { @@ -161,6 +162,15 @@ export default function Editor() { } = useYamlStore(); const { languages, setLanguages, resetLanguages } = useLanguagesStore(); const { setCountrySections } = useCountryStore(); + + const organisations = organisationData.flatMap(data => + data.organisations.map(organisation => ({ + text: getLocalizedText(organisation.name, i18n.language), + value: organisation.id, + group: getLocalizedText(data.name, i18n.language) + " (" + getLocalizedText(data.abbreviation, i18n.language) + ")", + })) + ); + const { showCountryExtensionVersion, setShowCountryExtensionVersion } = useITCountrySpecific(); const getNestedValue = ( @@ -283,14 +293,31 @@ export default function Editor() { [setValue] ); + const updateOrganisation = useCallback( + (value: Partial) => { + const uri = value.organisation?.uri; + + if (uri) { + const organisation = organisations.find(o => o.value === uri); + setValue("organisation.name", organisation?.text); + } else { + setValue("organisation", undefined) + } + }, + [organisations, setValue] + ) + useEffect(() => { const subscription = watch((value, { name }) => { if (name === "maintenance.type") { resetMaintenance(value as PublicCode); } + if (name === "organisation.uri") { + updateOrganisation(value as PublicCode) + } }); return () => subscription.unsubscribe(); - }, [watch, resetMaintenance]); + }, [watch, resetMaintenance, updateOrganisation]); //#endregion //#region form action handlers @@ -486,7 +513,14 @@ export default function Editor() { fieldName="applicationSuite" /> -
+
+ + fieldName="organisation.uri" + data={organisations} + filter="contains" + /> +
+
{languages @@ -495,7 +529,7 @@ export default function Editor() { className="languages" key={`publiccodeyml.description.${lang}`} > -
+
{t(`publiccodeyml.description.title`)} (in{" "} {displayName(lang, undefined, "language")})
@@ -503,14 +537,14 @@ export default function Editor() { {isDeprecatedFieldVisible( `description.${lang}.genericName` as never ) && ( - - - fieldName="genericName" - lang={lang} - deprecated - /> - - )} + + + fieldName="genericName" + lang={lang} + deprecated + /> + + )}
fieldName="localisedName" @@ -579,9 +613,6 @@ export default function Editor() { fieldName="isBasedOn" /> - - fieldName="organisation.uri" /> -
diff --git a/src/app/components/EditorAwards.tsx b/src/app/components/EditorAwards.tsx index 50514a41..0558b351 100644 --- a/src/app/components/EditorAwards.tsx +++ b/src/app/components/EditorAwards.tsx @@ -70,7 +70,7 @@ export default function EditorAwards({ lang }: Props): JSX.Element { return (
-
+