WIP etherpad integracija
parent
affae91fd9
commit
1ef66a3d75
|
@ -18,6 +18,7 @@ module:
|
|||
dblog: 0
|
||||
dynamic_page_cache: 0
|
||||
editor: 0
|
||||
etherpad_api: 0
|
||||
field: 0
|
||||
field_ui: 0
|
||||
file: 0
|
||||
|
|
|
@ -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-"
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<script setup="setup">
|
||||
|
||||
import { ref } from 'vue'
|
||||
|
||||
const { etherpadUrl, etherpadPrefix } = useRuntimeConfig().public
|
||||
|
||||
const props = defineProps({
|
||||
revisionId: String
|
||||
})
|
||||
|
||||
const embed = ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
const uuid = props.revisionId ? props.revisionId : crypto.randomUUID()
|
||||
const padUrl = `${etherpadUrl}p/${etherpadPrefix}${uuid}?showChat=false&showLineNumbers=false&toc=false`
|
||||
embed.value.src = padUrl
|
||||
window.location.hash = uuid
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<iframe ref="embed" class="etherpad-textarea" />
|
||||
</template>
|
|
@ -31,7 +31,7 @@ const oddajPredlog = data => {
|
|||
<input name="naslov" type="text" v-model="naslov">
|
||||
|
||||
<label for="tekst">Besedilo</label>
|
||||
<textarea name="tekst" v-model="tekst" />
|
||||
<EtherpadTextarea />
|
||||
|
||||
<label for="email">E-poštni naslov</label>
|
||||
<input name="email" type="email" v-model="email">
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -43,3 +43,7 @@ details > summary {
|
|||
border: 2px solid black;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.etherpad-textarea {
|
||||
height: 25rem;
|
||||
}
|
||||
|
|
|
@ -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'
|
|
@ -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
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the Etherpad API module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function etherpad_api_install() {
|
||||
\Drupal::messenger()->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;
|
||||
}
|
|
@ -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
|
|
@ -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'
|
|
@ -0,0 +1,5 @@
|
|||
services:
|
||||
path_processor.etherpad_api:
|
||||
class: Drupal\etherpad_api\PathProcessor\EtherpadAPIPathProcessor
|
||||
tags:
|
||||
- { name: path_processor_inbound, priority: 1000 }
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\etherpad_api\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Returns responses for Etherpad API routes.
|
||||
*/
|
||||
class EtherpadApiController extends ControllerBase {
|
||||
protected $httpClient;
|
||||
protected $config;
|
||||
|
||||
public function __construct(ClientInterface $http_client, ConfigFactoryInterface $config_factory) {
|
||||
$this->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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\etherpad_api\Form;
|
||||
|
||||
use Drupal\Core\Form\ConfigFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Configure Etherpad API settings for this site.
|
||||
*/
|
||||
class SettingsForm extends ConfigFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'etherpad_api_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEditableConfigNames() {
|
||||
return ['etherpad_api.settings'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['url'] = [
|
||||
'#type' => '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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\etherpad_api\PathProcessor;
|
||||
|
||||
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Path processor to replace 'node' with 'content' in URLs.
|
||||
*/
|
||||
class EtherpadAPIPathProcessor implements InboundPathProcessorInterface {
|
||||
const PREFIX = '/etherpad-api/';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processInbound($path, Request $request) {
|
||||
if (strpos($path, self::PREFIX) === 0) {
|
||||
$subpath = substr($path, strlen(self::PREFIX));
|
||||
return '/etherpad-api/' . str_replace('/', ':', $subpath);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue