diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ffff2db --- /dev/null +++ b/.editorconfig @@ -0,0 +1,36 @@ +# EditorConfig Configurtaion file, for more details see: +# http://EditorConfig.org +# EditorConfig is a convention description, that could be interpreted +# by multiple editors to enforce common coding conventions for specific +# file types + +# top-most EditorConfig file: +# Will ignore other EditorConfig files in Home directory or upper tree level. +root = true + + +[*] # For All Files +# Unix-style newlines with a newline ending every file +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +# Set default charset +charset = utf-8 +# Indent style default +indent_style = space +# Max Line Length - a hard line wrap, should be disabled +max_line_length = off + +[*.{py,cfg,ini}] +# 4 space indentation +indent_size = 4 + +[*.{html,dtml,pt,zpt,xml,zcml,js,jsx,json,less,css,yaml,yml}] +# 2 space indentation +indent_size = 2 + +[{Makefile,.gitmodules}] +# Tab indentation (no size specified, but view as 4 spaces) +indent_style = tab +indent_size = unset +tab_width = unset diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..192ea8b --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +CHANGELOG.md +README.md diff --git a/.project.eslintrc.js b/.project.eslintrc.js new file mode 100644 index 0000000..6e39257 --- /dev/null +++ b/.project.eslintrc.js @@ -0,0 +1,50 @@ +const fs = require('fs'); +const path = require('path'); + +const projectRootPath = fs.realpathSync('./project'); // __dirname +const packageJson = require(path.join(projectRootPath, 'package.json')); + +let voltoPath = path.join(projectRootPath, 'node_modules/@plone/volto'); + +let configFile; +if (fs.existsSync(`${this.projectRootPath}/tsconfig.json`)) + configFile = `${this.projectRootPath}/tsconfig.json`; +else if (fs.existsSync(`${this.projectRootPath}/jsconfig.json`)) + configFile = `${this.projectRootPath}/jsconfig.json`; + +if (configFile) { + const jsConfig = require(configFile).compilerOptions; + const pathsConfig = jsConfig.paths; + if (pathsConfig['@plone/volto']) + voltoPath = `./${jsConfig.baseUrl}/${pathsConfig['@plone/volto'][0]}`; +} + +const AddonConfigurationRegistry = require(`${voltoPath}/addon-registry.js`); +const reg = new AddonConfigurationRegistry(projectRootPath); + +// Extends ESlint configuration for adding the aliases to `src` directories in Volto addons +const addonAliases = Object.keys(reg.packages).map((o) => [ + o, + reg.packages[o].modulePath, +]); + +module.exports = { + extends: `${voltoPath}/.eslintrc`, + settings: { + 'import/resolver': { + alias: { + map: [ + ['@plone/volto', '@plone/volto/src'], + ...addonAliases, + ['@package', `${__dirname}/src`], + ['@root', `${__dirname}/src`], + ['~', `${__dirname}/src`], + ], + extensions: ['.js', '.jsx', '.json'], + }, + 'babel-plugin-root-import': { + rootPathSuffix: 'src', + }, + }, + }, +}; diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d65dffd --- /dev/null +++ b/Makefile @@ -0,0 +1,67 @@ +# Yeoman Volto App development + +### Defensive settings for make: +# https://tech.davis-hansson.com/p/make/ +SHELL:=bash +.ONESHELL: +.SHELLFLAGS:=-xeu -o pipefail -O inherit_errexit -c +.SILENT: +.DELETE_ON_ERROR: +MAKEFLAGS+=--warn-undefined-variables +MAKEFLAGS+=--no-builtin-rules + +# Project settings +# Update the versions depending on your project requirements | Last Updated 2022-12-23 +DOCKER_IMAGE=plone/plone-backend:6.0 +KGS= +TESTING_ADDONS=plone.app.robotframework==2.0.0 plone.app.testing==7.0.0 +NODEBIN = ./node_modules/.bin + +# Plone 5 legacy +DOCKER_IMAGE5=plone/plone-backend:5.2.9 +KGS5=plone.restapi==8.32.6 plone.volto==4.0.0 plone.rest==2.0.0 + +DIR=$(shell basename $$(pwd)) +ADDON ?= "@Fosten/volto-farmOS" + +# Recipe snippets for reuse + +# We like colors +# From: https://coderwall.com/p/izxssa/colored-makefile-for-golang-projects +RED=`tput setaf 1` +GREEN=`tput setaf 2` +RESET=`tput sgr0` +YELLOW=`tput setaf 3` + + +# Top-level targets + +.PHONY: project +project: + npm install -g yo + npm install -g @plone/generator-volto + npm install -g mrs-developer + yo @plone/volto project --addon ${ADDON} --workspace "src/addons/${DIR}" --no-interactive + ln -sf $$(pwd) project/src/addons/ + cp .project.eslintrc.js .eslintrc.js + cd project && yarn + @echo "-------------------" + @echo "$(GREEN)Volto project is ready!$(RESET)" + @echo "$(RED)Now run: cd project && yarn start$(RESET)" + +.PHONY: all +all: project + +.PHONY: start-test-backend +start-test-backend: ## Start Test Plone Backend + @echo "$(GREEN)==> Start Test Plone Backend$(RESET)" + docker run -i --rm -e ZSERVER_HOST=0.0.0.0 -e ZSERVER_PORT=55001 -p 55001:55001 -e SITE=plone -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.volto:default-homepage -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.volto,plone.volto.cors -e ADDONS='plone.app.robotframework plone.app.contenttypes plone.restapi plone.volto' plone ./bin/robot-server plone.app.robotframework.testing.PLONE_ROBOT_TESTING + +.PHONY: start-backend-docker +start-backend-docker: ## Starts a Docker-based backend + @echo "$(GREEN)==> Start Docker-based Plone Backend$(RESET)" + docker run -it --rm --name=backend -p 8080:8080 -e SITE=Plone -e ADDONS='$(KGS)' $(DOCKER_IMAGE) + +.PHONY: help +help: ## Show this help. + @echo -e "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)" diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..2f4e1e8 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,17 @@ +module.exports = function (api) { + api.cache(true); + const presets = ['razzle/babel']; + const plugins = [ + [ + 'react-intl', // React Intl extractor, required for the whole i18n infrastructure to work + { + messagesDir: './build/messages/', + }, + ], + ]; + + return { + plugins, + presets, + }; +}; diff --git a/cypress.config.js b/cypress.config.js new file mode 100644 index 0000000..08d55e6 --- /dev/null +++ b/cypress.config.js @@ -0,0 +1,8 @@ +const { defineConfig } = require('cypress'); + +module.exports = defineConfig({ + e2e: { + baseUrl: 'http://localhost:3000', + specPattern: 'cypress/tests/**/*.cy.{js,jsx}', + }, +}); diff --git a/cypress/.gitkeep b/cypress/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/cypress/fixtures/broccoli.jpg b/cypress/fixtures/broccoli.jpg new file mode 100644 index 0000000..456706d Binary files /dev/null and b/cypress/fixtures/broccoli.jpg differ diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 0000000..02e4254 --- /dev/null +++ b/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/cypress/fixtures/file.pdf b/cypress/fixtures/file.pdf new file mode 100644 index 0000000..ef9c798 Binary files /dev/null and b/cypress/fixtures/file.pdf differ diff --git a/cypress/fixtures/image.png b/cypress/fixtures/image.png new file mode 100644 index 0000000..4c109ba Binary files /dev/null and b/cypress/fixtures/image.png differ diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js new file mode 100644 index 0000000..dffed25 --- /dev/null +++ b/cypress/plugins/index.js @@ -0,0 +1,17 @@ +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config +}; diff --git a/cypress/support/commands.js b/cypress/support/commands.js new file mode 100644 index 0000000..03fe48c --- /dev/null +++ b/cypress/support/commands.js @@ -0,0 +1,9 @@ +import '@plone/volto/cypress/add-commands'; + +// Set PLONE_SITE_ID and PLONE_API_URL as cypress environment variables +// if testing without using localhost or a site id of `plone`. + +// --- CUSTOM COMMANDS ------------------------------------------------------------- +Cypress.Commands.add('custom_command', () => { + // Custom code here... +}); diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js new file mode 100644 index 0000000..48912f7 --- /dev/null +++ b/cypress/support/e2e.js @@ -0,0 +1,14 @@ +import 'cypress-axe'; +import 'cypress-file-upload'; +import './commands'; +import { setup, teardown } from './reset-fixture'; + +beforeEach(function () { + cy.log('Setting up API fixture'); + setup(); +}); + +afterEach(function () { + cy.log('Tearing down API fixture'); + teardown(); +}); diff --git a/cypress/support/reset-fixture.js b/cypress/support/reset-fixture.js new file mode 100644 index 0000000..a9a5fad --- /dev/null +++ b/cypress/support/reset-fixture.js @@ -0,0 +1,45 @@ +function setup() { + const api_url = Cypress.env('API_PATH') || 'http://localhost:55001/plone'; + cy.request({ + method: 'POST', + url: `${api_url}/RobotRemote`, + headers: { Accept: 'text/xml', 'content-type': 'text/xml' }, + body: + 'run_keywordremote_zodb_setupplone.app.robotframework.testing.PLONE_ROBOT_TESTING', + }).then(() => cy.log('Setting up API fixture')); +} + +function teardown() { + const api_url = Cypress.env('API_PATH') || 'http://localhost:55001/plone'; + cy.request({ + method: 'POST', + url: `${api_url}/RobotRemote`, + headers: { Accept: 'text/xml', 'content-type': 'text/xml' }, + body: + 'run_keywordremote_zodb_teardownplone.app.robotframework.testing.PLONE_ROBOT_TESTING', + }).then(() => cy.log('Tearing down API fixture')); +} + +function main() { + const command = process.argv[2]; + switch (command) { + case 'setup': + setup(); + break; + case 'teardown': + teardown(); + break; + default: + setup(); + } +} + +// This is the equivalent of `if __name__ == '__main__'` in Python :) +if (require.main === module) { + main(); +} + +module.exports = { + setup, + teardown, +}; diff --git a/cypress/tests/.gitkeep b/cypress/tests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/jest-addon.config.js b/jest-addon.config.js new file mode 100644 index 0000000..f66acd4 --- /dev/null +++ b/jest-addon.config.js @@ -0,0 +1,33 @@ +module.exports = { + testMatch: ['**/src/addons/**/?(*.)+(spec|test).[jt]s?(x)'], + collectCoverageFrom: [ + 'src/addons/**/src/**/*.{js,jsx,ts,tsx}', + '!src/**/*.d.ts', + ], + transformIgnorePatterns: ['node_modules/(?!(volto-slate|@plone/volto)/)'], + moduleNameMapper: { + '@plone/volto/cypress': '/node_modules/@plone/volto/cypress', + '@plone/volto/babel': '/node_modules/@plone/volto/babel', + '@plone/volto/(.*)$': '/node_modules/@plone/volto/src/$1', + '@package/(.*)$': '/src/$1', + '@root/(.*)$': '/src/$1', + '~/(.*)$': '/src/$1', + 'load-volto-addons': + '/node_modules/@plone/volto/jest-addons-loader.js', + '\\.(css|less|scss|sass)$': 'identity-obj-proxy', + }, + transform: { + '^.+\\.js(x)?$': 'babel-jest', + '^.+\\.(png)$': 'jest-file', + '^.+\\.(jpg)$': 'jest-file', + '^.+\\.(svg)$': './node_modules/@plone/volto/jest-svgsystem-transform.js', + }, + coverageThreshold: { + global: { + branches: 5, + functions: 5, + lines: 5, + statements: 5, + }, + }, +}; diff --git a/locales/volto.pot b/locales/volto.pot new file mode 100644 index 0000000..1b22bc0 --- /dev/null +++ b/locales/volto.pot @@ -0,0 +1,14 @@ +msgid "" +msgstr "" +"Project-Id-Version: Plone\n" +"POT-Creation-Date: 2021-01-29T12:34:47.097Z\n" +"Last-Translator: Plone i18n \n" +"Language-Team: Plone i18n \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Language-Code: en\n" +"Language-Name: English\n" +"Preferred-Encodings: utf-8\n" +"Domain: volto\n" diff --git a/package.json b/package.json new file mode 100644 index 0000000..67f426f --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "@Fosten/volto-farmOS", + "version": "0.1.0", + "description": "volto-farmOS: Volto add-on", + "main": "src/index.js", + "license": "MIT", + "keywords": [ + "volto-addon", + "volto", + "plone", + "react" + ], + "scripts": { + "i18n": "rm -rf build/messages && NODE_ENV=production i18n --addon" + }, + "devDependencies": { + "@plone/scripts": "*" + } +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..cb042f0 --- /dev/null +++ b/src/index.js @@ -0,0 +1,5 @@ +const applyConfig = (config) => { + return config; +}; + +export default applyConfig;