diff --git a/config/sync/core.extension.yml b/config/sync/core.extension.yml
index a42ca64..17d70f8 100644
--- a/config/sync/core.extension.yml
+++ b/config/sync/core.extension.yml
@@ -18,6 +18,7 @@ module:
dblog: 0
dynamic_page_cache: 0
editor: 0
+ etherpad_api: 0
field: 0
field_ui: 0
file: 0
diff --git a/nuxt/.env.dist b/nuxt/.env.dist
index bb7a59d..fb8ea11 100644
--- a/nuxt/.env.dist
+++ b/nuxt/.env.dist
@@ -1,3 +1,5 @@
BASE_URL="https://yufu-manifest.ddev.site"
JSONAPI_PATH="/jsonapi"
FILE_PATH="/sites/default/files"
+ETHERPAD_URL="https://pisi.kompot.si/"
+ETHERPAD_PREFIX="yufu-"
diff --git a/nuxt/components/EtherpadTextarea.vue b/nuxt/components/EtherpadTextarea.vue
new file mode 100644
index 0000000..d302fc2
--- /dev/null
+++ b/nuxt/components/EtherpadTextarea.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
diff --git a/nuxt/components/PojemForm.vue b/nuxt/components/PojemForm.vue
index e3b9d89..064b682 100644
--- a/nuxt/components/PojemForm.vue
+++ b/nuxt/components/PojemForm.vue
@@ -31,7 +31,7 @@ const oddajPredlog = data => {
-
+
diff --git a/nuxt/composables/api.js b/nuxt/composables/api.js
index 0b618ca..d1c89d8 100644
--- a/nuxt/composables/api.js
+++ b/nuxt/composables/api.js
@@ -1,8 +1,7 @@
import jsonapi from 'jsonapi-serializer'
export const useApi = () => {
- const baseUrl = useRuntimeConfig().public.baseUrl
- const jsonapiPath = useRuntimeConfig().public.jsonapiPath
+ const { baseUrl, jsonapiPath } = useRuntimeConfig().public
const apiBaseUrl = `${baseUrl}${jsonapiPath}`
const headers = {
diff --git a/nuxt/nuxt.config.js b/nuxt/nuxt.config.js
index 76361d1..2271331 100644
--- a/nuxt/nuxt.config.js
+++ b/nuxt/nuxt.config.js
@@ -2,7 +2,7 @@ export default defineNuxtConfig({
// Global page headers: https://go.nuxtjs.dev/config-head
app: {
head: {
- title: '...Hm!',
+ title: 'Jugofuturistični manifest',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
@@ -35,6 +35,8 @@ export default defineNuxtConfig({
public: {
baseUrl: process.env.BASE_URL,
jsonapiPath: process.env.JSONAPI_PATH,
+ etherpadUrl: process.env.ETHERPAD_URL,
+ etherpadPrefix: process.env.ETHERPAD_PREFIX
}
}
})
diff --git a/nuxt/package-lock.json b/nuxt/package-lock.json
index bd0a3ba..313cd2e 100644
--- a/nuxt/package-lock.json
+++ b/nuxt/package-lock.json
@@ -6,10 +6,8 @@
"": {
"hasInstallScript": true,
"dependencies": {
- "axios": "^1.4.0",
"druxt": "^0.21.0",
"jsonapi-serializer": "^3.6.7",
- "lodash": "^4.17.21",
"nuxt-proxy": "^0.4.1",
"pinia": "^2.0.32"
},
@@ -2900,7 +2898,8 @@
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "peer": true
},
"node_modules/autoprefixer": {
"version": "10.4.13",
@@ -2951,6 +2950,7 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
+ "peer": true,
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
@@ -3243,9 +3243,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001457",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz",
- "integrity": "sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==",
+ "version": "1.0.30001541",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001541.tgz",
+ "integrity": "sha512-bLOsqxDgTqUBkzxbNlSBt8annkDpQB9NdzdTbO2ooJ+eC/IQcvDspDc058g84ejCelF7vHUx57KIOjEecOHXaw==",
"funding": [
{
"type": "opencollective",
@@ -3254,6 +3254,10 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
]
},
@@ -3576,6 +3580,7 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "peer": true,
"dependencies": {
"delayed-stream": "~1.0.0"
},
@@ -4003,6 +4008,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "peer": true,
"engines": {
"node": ">=0.4.0"
}
@@ -5872,6 +5878,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "peer": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -7695,6 +7702,7 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "peer": true,
"engines": {
"node": ">= 0.6"
}
@@ -7703,6 +7711,7 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "peer": true,
"dependencies": {
"mime-db": "1.52.0"
},
@@ -9302,7 +9311,8 @@
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "peer": true
},
"node_modules/prr": {
"version": "1.0.1",
diff --git a/nuxt/public/css/stajl.css b/nuxt/public/css/stajl.css
index 6ee78d8..cbdb605 100644
--- a/nuxt/public/css/stajl.css
+++ b/nuxt/public/css/stajl.css
@@ -43,3 +43,7 @@ details > summary {
border: 2px solid black;
cursor: pointer;
}
+
+.etherpad-textarea {
+ height: 25rem;
+}
diff --git a/web/modules/custom/etherpad_api/config/schema/etherpad_api.schema.yml b/web/modules/custom/etherpad_api/config/schema/etherpad_api.schema.yml
new file mode 100644
index 0000000..28a21b0
--- /dev/null
+++ b/web/modules/custom/etherpad_api/config/schema/etherpad_api.schema.yml
@@ -0,0 +1,11 @@
+# Schema for the configuration files of the Etherpad API module.
+etherpad_api.settings:
+ type: config_object
+ label: 'Etherpad API settings'
+ mapping:
+ url:
+ type: string
+ label: 'API URL of etherpad instance'
+ key:
+ type: string
+ label: 'API key of etherpad instance'
diff --git a/web/modules/custom/etherpad_api/etherpad_api.info.yml b/web/modules/custom/etherpad_api/etherpad_api.info.yml
new file mode 100644
index 0000000..21a2976
--- /dev/null
+++ b/web/modules/custom/etherpad_api/etherpad_api.info.yml
@@ -0,0 +1,6 @@
+name: Etherpad API
+type: module
+description: API endpoint for working with an etherpad instance
+package: Yufu
+configure: etherpad_api.settings
+core_version_requirement: ^9 || ^10
diff --git a/web/modules/custom/etherpad_api/etherpad_api.install b/web/modules/custom/etherpad_api/etherpad_api.install
new file mode 100644
index 0000000..b1b9356
--- /dev/null
+++ b/web/modules/custom/etherpad_api/etherpad_api.install
@@ -0,0 +1,96 @@
+addStatus(__FUNCTION__);
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function etherpad_api_uninstall() {
+ \Drupal::messenger()->addStatus(__FUNCTION__);
+}
+
+/**
+ * Implements hook_schema().
+ */
+function etherpad_api_schema() {
+ $schema['etherpad_api_example'] = [
+ 'description' => 'Table description.',
+ 'fields' => [
+ 'id' => [
+ 'type' => 'serial',
+ 'not null' => TRUE,
+ 'description' => 'Primary Key: Unique record ID.',
+ ],
+ 'uid' => [
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'The {users}.uid of the user who created the record.',
+ ],
+ 'status' => [
+ 'description' => 'Boolean indicating whether this record is active.',
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'size' => 'tiny',
+ ],
+ 'type' => [
+ 'type' => 'varchar_ascii',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'Type of the record.',
+ ],
+ 'created' => [
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'Timestamp when the record was created.',
+ ],
+ 'data' => [
+ 'type' => 'blob',
+ 'not null' => TRUE,
+ 'size' => 'big',
+ 'description' => 'The arbitrary data for the item.',
+ ],
+ ],
+ 'primary key' => ['id'],
+ 'indexes' => [
+ 'type' => ['type'],
+ 'uid' => ['uid'],
+ 'status' => ['status'],
+ ],
+ ];
+
+ return $schema;
+}
+
+/**
+ * Implements hook_requirements().
+ */
+function etherpad_api_requirements($phase) {
+ $requirements = [];
+
+ if ($phase == 'runtime') {
+ $value = mt_rand(0, 100);
+ $requirements['etherpad_api_status'] = [
+ 'title' => t('Etherpad API status'),
+ 'value' => t('Etherpad API value: @value', ['@value' => $value]),
+ 'severity' => $value > 50 ? REQUIREMENT_INFO : REQUIREMENT_WARNING,
+ ];
+ }
+
+ return $requirements;
+}
diff --git a/web/modules/custom/etherpad_api/etherpad_api.links.menu.yml b/web/modules/custom/etherpad_api/etherpad_api.links.menu.yml
new file mode 100644
index 0000000..f478566
--- /dev/null
+++ b/web/modules/custom/etherpad_api/etherpad_api.links.menu.yml
@@ -0,0 +1,6 @@
+etherpad_api.settings_form:
+ title: 'Etherpad API'
+ description: 'Configure Etherpad API.'
+ parent: system.admin_config_system
+ route_name: etherpad_api.settings_form
+ weight: 10
diff --git a/web/modules/custom/etherpad_api/etherpad_api.routing.yml b/web/modules/custom/etherpad_api/etherpad_api.routing.yml
new file mode 100644
index 0000000..e264194
--- /dev/null
+++ b/web/modules/custom/etherpad_api/etherpad_api.routing.yml
@@ -0,0 +1,15 @@
+etherpad_api.example:
+ path: '/etherpad-api/{components}'
+ defaults:
+ _title: 'Etherpad API'
+ _controller: '\Drupal\etherpad_api\Controller\EtherpadApiController::build'
+ requirements:
+ _permission: 'access content'
+
+etherpad_api.settings_form:
+ path: '/admin/config/system/etherpad-api'
+ defaults:
+ _title: 'Etherpad API settings'
+ _form: 'Drupal\etherpad_api\Form\SettingsForm'
+ requirements:
+ _permission: 'administer etherpad_api configuration'
diff --git a/web/modules/custom/etherpad_api/etherpad_api.services.yml b/web/modules/custom/etherpad_api/etherpad_api.services.yml
new file mode 100644
index 0000000..4450233
--- /dev/null
+++ b/web/modules/custom/etherpad_api/etherpad_api.services.yml
@@ -0,0 +1,5 @@
+services:
+ path_processor.etherpad_api:
+ class: Drupal\etherpad_api\PathProcessor\EtherpadAPIPathProcessor
+ tags:
+ - { name: path_processor_inbound, priority: 1000 }
diff --git a/web/modules/custom/etherpad_api/src/Controller/EtherpadApiController.php b/web/modules/custom/etherpad_api/src/Controller/EtherpadApiController.php
new file mode 100644
index 0000000..86dc1cd
--- /dev/null
+++ b/web/modules/custom/etherpad_api/src/Controller/EtherpadApiController.php
@@ -0,0 +1,51 @@
+httpClient = $http_client;
+ $this->configFactory = $config_factory;
+ }
+
+ public static function create(ContainerInterface $container) {
+ return new static($container->get('http_client'), $container->get('config.factory'));
+ }
+
+ /**
+ * Builds the response.
+ */
+ public function build($components, Request $request) {
+ $baseUrl = $this->config('etherpad_api.settings')->get('url');
+ $apiKey = $this->config('etherpad_api.settings')->get('key');
+
+ $params = $request->getQueryString();
+ if ($params) {
+ $params .= "&apikey=$apiKey";
+ } else {
+ $params = "apikey=$apiKey";
+ }
+ $uri = $baseUrl . str_replace(':', '/', $components) . "?$params";
+
+ $method = $request->getMethod();
+ try {
+ return $this->httpClient->request($method, $uri);
+ } catch (ClientException $exception) {
+ return new Response($exception->getMessage(), $exception->getCode());
+ }
+ }
+}
diff --git a/web/modules/custom/etherpad_api/src/Form/SettingsForm.php b/web/modules/custom/etherpad_api/src/Form/SettingsForm.php
new file mode 100644
index 0000000..d870c9c
--- /dev/null
+++ b/web/modules/custom/etherpad_api/src/Form/SettingsForm.php
@@ -0,0 +1,68 @@
+ 'textfield',
+ '#title' => $this->t('Etherpad API URL'),
+ '#default_value' => $this->config('etherpad_api.settings')->get('url'),
+ ];
+ $form['key'] = [
+ '#type' => 'textfield',
+ '#title' => $this->t('Etherpad API key (found in instance root folder)'),
+ '#default_value' => $this->config('etherpad_api.settings')->get('key'),
+ ];
+ return parent::buildForm($form, $form_state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, FormStateInterface $form_state) {
+ if (!$form_state->getValue('url')) {
+ $form_state->setErrorByName('url', $this->t('The value is required.'));
+ }
+ if (!$form_state->getValue('key')) {
+ $form_state->setErrorByName('key', $this->t('The value is required.'));
+ }
+ parent::validateForm($form, $form_state);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $this->config('etherpad_api.settings')
+ ->set('url', $form_state->getValue('url'))
+ ->set('key', $form_state->getValue('key'))
+ ->save();
+ parent::submitForm($form, $form_state);
+ }
+
+}
diff --git a/web/modules/custom/etherpad_api/src/PathProcessor/EtherpadAPIPathProcessor.php b/web/modules/custom/etherpad_api/src/PathProcessor/EtherpadAPIPathProcessor.php
new file mode 100644
index 0000000..54a72c6
--- /dev/null
+++ b/web/modules/custom/etherpad_api/src/PathProcessor/EtherpadAPIPathProcessor.php
@@ -0,0 +1,25 @@
+