1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2025-11-23 22:05:15 +02:00

Переработка главной страницы доков

This commit is contained in:
Anton Titovets
2025-06-29 18:55:34 +03:00
parent 408473f4ec
commit a2cf13403b
20 changed files with 1002 additions and 353 deletions

View File

@@ -0,0 +1,68 @@
import React from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';
import Link from '@docusaurus/Link'; // Импортируем компонент Link из Docusaurus
const FeatureItem = ({ imageUrl, title, description }) => {
return (
<div className={clsx(styles.featureItem,)}>
<div className={styles.featureImageWrapper}>
<img src={imageUrl} alt={title} className={styles.featureImg} />
</div>
<div className={styles.featureContent}>
<h3 className={styles.featureTitle}>{title}</h3>
<div className={styles.featureDesc}>
{typeof description === 'string' ? <p>{description}</p> : description}
</div>
</div>
</div>
);
};
const AlternatingFeatures = () => {
const features = [
{
title: "Сотни методов для десятков сервисов",
description: (
<p>
ОПИ состоит из большого набора разнообразных методов для множества известных API и технологий, будь то облачные Telegram, Bitrix24 и Google Drive, или же локальные S3, MySQL и PostgreSQL. Ознакомится с полным списком доступных сервисов можно на
<Link to="/docs/Instructions/Start" > вводной странице документации</Link>
</p>
),
imageUrl: "/img/f1.png"
},
{
title: "Три платформы - одно решение",
description:(
<p>
Открытый пакет интеграций прдоставляет единый набор функций сразу в трех вариантах: как расширение для 1С:Предприятие 8, как пакет для OneScript и как полноценное приложение для командной строки. Это позволяет удобно использовать его методы для решения широкого спектра задач, выбирая форму поствки в зависимости от конкретного сценария работы. Заранее собранные файлы для каждого из этих вариантов всегда можно найти в
<Link to="https://github.com/Bayselonarrend/OpenIntegrations/releases"> релизах ОПИ на GitHub </Link>
- остается только скачать и запустить!
</p>
),
imageUrl: "/img/f2.png"
},
{
title: "Свобода открытого кода",
description: "Проект имеет открытый исходный коди и распространяется под лицензией MIT. Это означает, что вы можете использовать его в любых своих проектах, даже если они коммерческие и имеют закрытые исходники. Вся кодовая база проекта доступна публично в репозитории на GitHub и доступна для использования, а также полного или частичного изменения. Единственное условие - сохранение текста лицензии, который находится в каждом из файлов с кодом",
imageUrl: "/img/f3.png"
},
];
return (
<section className={styles.features}>
<div className="container">
{features.map((feature, idx) => (
<FeatureItem
key={idx}
{...feature}
isReversed={idx % 2 !== 0} // Чередуем порядок
/>
))}
</div>
</section>
);
};
export default AlternatingFeatures;

View File

@@ -0,0 +1,72 @@
.features {
padding: 4rem 0;
}
.featureItem {
display: flex;
align-items: center;
margin-bottom: 4rem;
gap: 2rem;
}
.featureImage {
padding: 1rem;
}
.featureImageWrapper {
flex: 1;
min-width: 200px;
height: 200px;
display: flex;
align-items: center; /* Выравнивание по вертикали */
justify-content: center; /* Выравнивание по горизонтали */
overflow: hidden;
}
.featureImg {
width: 100%;
height: 100%;
object-fit: cover; /* Сохраняет пропорции, обрезая если нужно */
transition: transform 0.3s ease;
}
.featureImg:hover {
transform: scale(1.02);
}
.featureContent {
padding: 1rem;
}
.featureTitle {
font-size: 1.8rem;
margin-bottom: 1.5rem;
}
.featureDesc {
font-size: 1.1rem;
line-height: 1.6;
}
/* Обратный порядок для четных элементов */
.reversed {
flex-direction: row-reverse;
}
@media (max-width: 996px) {
.featureItem,
.reversed {
flex-direction: column;
}
.featureImage,
.featureContent {
width: 100%;
max-width: 600px;
margin: 0 auto;
}
.featureTitle {
margin-top: 1.5rem;
}
}

View File

@@ -1,100 +1,61 @@
import clsx from 'clsx';
import Heading from '@theme/Heading';
import styles from './styles.module.css';
const FeatureList = [
{
title: 'Простота и гибкость',
Svg: require('@site/static/img/tools.svg').default,
description: (
<>
Пакет содержит множество методов для работы с различными API. Эти методы не треубют глубокого погружения в тонкости работы, но и не ограничивают вас в возможности их модификации
</>
),
},
{
title: 'Лёгкость внедрения',
Svg: require('@site/static/img/delivery.svg').default,
description: (
<>
ОПИ легко интегрировать в любой проект: в виде проекта EDT, 1C-расширения или пакета OneScript. Для интеграции, независимой от конретных технологий, есть CLI версия под Windows и Linux
</>
),
},
{
title: 'Подробная документация',
Svg: require('@site/static/img/books.svg').default,
description: (
<>
У ОПИ есть подробная документация, а код структурирован и дополнен комментариями. Если же у вас все таки возникнут дополнительные вопросы, то вы всегда можете задать их в Issues на Github
</>
),
},
];
function Feature({Svg, title, description}) {
return (
<div className={clsx('col col--4')}>
<div className="text--center">
<Svg className={styles.featureSvg} role="img" />
</div>
<div className="text--center padding-horiz--md">
<Heading as="h3">{title}</Heading>
<p>{description}</p>
</div>
</div>
);
}
export default function HomepageFeatures() {
return (
<section className={styles.features}>
<div className="container">
<div className="row">
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
<br/>
<hr/>
<br/>
<br/>
<section className={styles.container}>
<span className={styles.looptext}>
<a className={styles.ico} href="/docs/Instructions/Telegram/"> <img src={require('../../../static/img/APIs/Telegram.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/VK/"><img src={require('../../../static/img/APIs/VK.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Viber/"><img src={require('../../../static/img/APIs/Viber.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Twitter/"><img src={require('../../../static/img/APIs/Twitter.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Notion/"><img src={require('../../../static/img/APIs/Notion.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Yandex_Disk/"><img src={require('../../../static/img/APIs/YandexDisk.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Google_Calendar/"><img src={require('../../../static/img/APIs/GoogleCalendar.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Google_Drive/"><img src={require('../../../static/img/APIs/GoogleDrive.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Google_Sheets/"> <img src={require('../../../static/img/APIs/GoogleSheets.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/Slack/"> <img src={require('../../../static/img/APIs/Slack.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/Airtable/"> <img src={require('../../../static/img/APIs/Airtable.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/Telegram/"> <img src={require('../../../static/img/APIs/Telegram.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/Telegram/"> <img src={require('../../../static/img/APIs/Dropbox.png').default} width='32px' /></a>
</span>
<span className={styles.looptext}>
<a className={styles.ico} href="/docs/Instructions/Telegram/"> <img src={require('../../../static/img/APIs/Telegram.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/VK/"><img src={require('../../../static/img/APIs/VK.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Viber/"><img src={require('../../../static/img/APIs/Viber.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Twitter/"><img src={require('../../../static/img/APIs/Twitter.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Notion/"><img src={require('../../../static/img/APIs/Notion.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Yandex_Disk/"><img src={require('../../../static/img/APIs/YandexDisk.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Google_Calendar/"><img src={require('../../../static/img/APIs/GoogleCalendar.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Google_Drive/"><img src={require('../../../static/img/APIs/GoogleDrive.png').default} width='32px'/> </a>
<a className={styles.ico} href="/docs/Instructions/Google_Sheets/"> <img src={require('../../../static/img/APIs/GoogleSheets.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/Slack/"> <img src={require('../../../static/img/APIs/Slack.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/Airtable/"> <img src={require('../../../static/img/APIs/Airtable.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/Telegram/"> <img src={require('../../../static/img/APIs/Telegram.png').default} width='32px' /></a>
<a className={styles.ico} href="/docs/Instructions/Telegram/"> <img src={require('../../../static/img/APIs/Dropbox.png').default} width='32px' /></a>
</span>
</section>
</div>
</section>
);
}
import clsx from 'clsx';
import Heading from '@theme/Heading';
import styles from './styles.module.css';
const FeatureList = [
{
title: 'Простота и гибкость',
Svg: require('@site/static/img/tools.svg').default,
description: (
<>
Пакет содержит множество методов для работы с различными API. Эти методы не треубют глубокого погружения в тонкости работы, но и не ограничивают вас в возможности их модификации
</>
),
},
{
title: 'Лёгкость внедрения',
Svg: require('@site/static/img/delivery.svg').default,
description: (
<>
ОПИ легко интегрировать в любой проект: в виде проекта EDT, 1C-расширения или пакета OneScript. Для интеграции, независимой от конретных технологий, есть CLI версия под Windows и Linux
</>
),
},
{
title: 'Подробная документация',
Svg: require('@site/static/img/books.svg').default,
description: (
<>
У ОПИ есть подробная документация, а код структурирован и дополнен комментариями. Если же у вас все таки возникнут дополнительные вопросы, то вы всегда можете задать их в Issues на Github
</>
),
},
];
function Feature({ Svg, title, description }) {
return (
<div className={clsx('col col--4')}>
<div className="text--center">
<Svg className={styles.featureSvg} role="img" />
</div>
<div className="text--center padding-horiz--md">
<Heading as="h3">{title}</Heading>
<p>{description}</p>
</div>
</div>
);
}
export default function HomepageFeatures() {
return (
<section className={styles.features}>
<div className="container">
<div className="row">
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
);
}

View File

@@ -1,55 +1,59 @@
marquee{
padding: auto;
}
.api{
margin-right: 200px;
}
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
}
.featureSvg {
height: 80px;
width: 80px;
}
.ico{
padding: 176px;
}
.hero__title{
font-size: 10px;
}
.container {
display: flex;
white-space: nowrap;
width: 100%;
height: clamp(3em, 10vw, 6em);
overflow: hidden;
font-family: sans-serif;
}
.looptext {
animation: loopText 27s infinite linear;
}
@keyframes loopText {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
marquee{
padding: auto;
}
.api{
margin-right: 300px;
}
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
color: black;
margin-top: 23px;
}
.featureSvg {
height: 80px;
width: 80px;
}
.ico{
padding: 176px;
}
.hero__title{
font-size: 10px;
}
.container {
display: flex;
white-space: nowrap;
width: 100%;
height: clamp(3em, 10vw, 6em);
overflow: hidden;
font-family: sans-serif;
margin-top: 200px;
}
.looptext {
animation: loopText 27s infinite linear;
}
@keyframes loopText {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}

View File

@@ -22,6 +22,10 @@ p{
font-weight: lighter;
}
h3{
font-weight: 400;
}
@media (min-width: 996px) {
.main-wrapper,.navbar{

View File

@@ -1,60 +1,85 @@
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import HomepageFeatures from '@site/src/components/HomepageFeatures';
import Heading from '@theme/Heading';
import styles from './index.module.css';
function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<img src="/img/logo.svg" className={styles.biglogo}/>
<Heading as="p" className="hero__title">
{siteConfig.title}
</Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<div className={styles.button}><Link
className="button button--secondary button--bg"
to="/docs/Instructions/Start">
🧭 Документация
</Link>
</div>
<div className={styles.button}><Link
className="button button--secondary button--bg"
to="https://github.com/Bayselonarrend/OpenIntegrations/releases/latest">
Скачать
</Link>
</div>
<div className={styles.button}><Link
className="button button--secondary button--bg"
to="https://en.openintegrations.dev">
English version
</Link>
</div>
</div>
</div>
</header>
);
}
export default function Home() {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
title={`Открытый пакет интеграций`}
description="ОПИ - пакет интеграций с популярными API для 1С:Enterprise и OneScript">
<HomepageHeader />
<main>
<HomepageFeatures />
</main>
</Layout>
);
}
import React, { useEffect } from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import AlternatingFeatures from '@site/src/components/AlternatingFeatures';
import Heading from '@theme/Heading';
import styles from './index.module.css';
function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
useEffect(() => {
// Создаем частицы только для header
const header = document.querySelector(`.${styles.heroBanner}`);
if (!header) return;
const particleCount = 30;
const particles = [];
for (let i = 0; i < particleCount; i++) {
const particle = document.createElement('div');
particle.className = styles.particle;
// Позиционирование внутри header
particle.style.left = `${Math.random() * 100}%`;
particle.style.top = `${Math.random() * 100}%`;
particle.style.width = `${Math.random() * 3 + 1}px`;
particle.style.height = particle.style.width;
particle.style.animationDuration = `${Math.random() * 10 + 5}s`;
particle.style.animationDelay = `${Math.random() * 2}s`;
header.appendChild(particle);
particles.push(particle);
}
return () => {
particles.forEach(p => p.remove());
};
}, []);
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<img src="/img/logo.svg" className={styles.biglogo}/>
<Heading as="p" className="hero__title">
{siteConfig.title}
</Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<div className={styles.button}>
<Link className="button button--secondary button--bg" to="/docs/Instructions/Start">
🧭 Документация
</Link>
</div>
<div className={styles.button}>
<Link className="button button--secondary button--bg" to="https://github.com/Bayselonarrend/OpenIntegrations/releases/latest">
Скачать
</Link>
</div>
<div className={styles.button}>
<Link className="button button--secondary button--bg" to="https://en.openintegrations.dev">
🌐 English version
</Link>
</div>
</div>
</div>
</header>
);
}
export default function Home() {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
title={`Открытый пакет интеграций`}
description="ОПИ - пакет интеграций с популярными API для 1С:Enterprise и OneScript">
<HomepageHeader />
<main>
<br/><hr/>
<AlternatingFeatures />
</main>
</Layout>
);
}

View File

@@ -1,42 +1,71 @@
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.heroBanner {
padding: 3rem 2rem 0;
text-align: center;
position: relative;
overflow: hidden;
color: black;
margin-top: -50px;
}
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
.biglogo{
margin-top: 35px;
}
}
.buttons {
display: flex;
align-items: center;
justify-content: center;
}
.button{
margin: 10px;
}
.biglogo{
width: 20%;
height: 20%;
}
.heroBanner_src-pages-index-module {
padding-bottom: 30px;
}
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.heroBanner {
padding: 3rem 2rem 0 7rem;
text-align: left;
position: relative;
overflow: hidden;
color: black;
margin-top: 20px;
}
.particle {
position: absolute;
background-color: rgba(0, 63, 19, 0.452);
border-radius: 50%;
pointer-events: none;
animation: float linear infinite;
}
@keyframes float {
0% {
transform: translateY(0) translateX(0);
opacity: 1;
}
50% {
transform: translateY(-50px) translateX(20px);
opacity: 0.7;
}
100% {
transform: translateY(0) translateX(0);
opacity: 1;
}
}
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
.biglogo{
margin-top: 35px;
}
}
.buttons {
display: flex;
align-items: left;
justify-content: ltft;
margin-left: -10px;
}
.button{
margin: 10px;
}
.biglogo{
width: 128px;
height: 128px;
margin-bottom: -15px;
margin-left: -15px;
}
.heroBanner_src-pages-index-module {
padding-bottom: 30px;
}

View File

@@ -1,75 +1,75 @@
import React, { useEffect } from 'react';
import Layout from '@theme-original/Layout';
import Head from '@docusaurus/Head';
import { useLocation } from '@docusaurus/router';
export default function CustomLayout(props) {
const location = useLocation();
useEffect(() => {
// Проверяем, находимся ли мы на странице документации
if (!location.pathname.startsWith('/docs/')) {
return; // Если нет, не добавляем блок
}
// Удаляем предыдущий блок и скрипт, если они существуют
const existingAdContainer = document.getElementById('yandex_rtb_R-A-12294791-5');
if (existingAdContainer) {
existingAdContainer.innerHTML = ''; // Очищаем контейнер перед перерендерингом
}
// Создаем контейнер для второго рекламного блока, если он не существует
let adContainer = existingAdContainer;
if (!adContainer) {
adContainer = document.createElement('div');
adContainer.id = 'yandex_rtb_R-A-12294791-5';
adContainer.style.marginTop = '20px'; // Добавим отступ для красоты
// Находим элемент кнопок "Previous" и "Next" и вставляем перед ним
const paginationElement = document.querySelector('.pagination-nav');
if (paginationElement) {
paginationElement.parentNode.insertBefore(adContainer, paginationElement);
} else {
// Если кнопок нет, добавляем контейнер в конец body
document.body.appendChild(adContainer);
}
}
// Создаем скрипт для рендеринга рекламы
const script = document.createElement('script');
script.innerHTML = `
window.yaContextCb.push(() => {
Ya.Context.AdvManager.destroy('yandex_rtb_R-A-12294791-5'); // Удаляем предыдущий экземпляр блока
Ya.Context.AdvManager.render({
"blockId": "R-A-12294791-3",
"type": "floorAd",
"platform": "touch"
});
Ya.Context.AdvManager.render({
"blockId": "R-A-12294791-5",
"renderTo": "yandex_rtb_R-A-12294791-5"
});
});
`;
document.body.appendChild(script);
// Удаляем элементы при размонтировании компонента
return () => {
script.remove();
adContainer.innerHTML = ''; // Очищаем контейнер при размонтировании
};
}, [location.pathname]); // Перезапуск эффекта при изменении пути
return (
<>
<Head>
<script>
window.yaContextCb = window.yaContextCb || [];
</script>
<script src="https://yandex.ru/ads/system/context.js" async></script>
</Head>
<Layout {...props} />
</>
);
}
import React, { useEffect } from 'react';
import Layout from '@theme-original/Layout';
import Head from '@docusaurus/Head';
import { useLocation } from '@docusaurus/router';
export default function CustomLayout(props) {
const location = useLocation();
useEffect(() => {
// Проверяем, находимся ли мы на странице документации
if (!location.pathname.startsWith('/docs/')) {
return; // Если нет, не добавляем блок
}
// Удаляем предыдущий блок и скрипт, если они существуют
const existingAdContainer = document.getElementById('yandex_rtb_R-A-12294791-5');
if (existingAdContainer) {
existingAdContainer.innerHTML = ''; // Очищаем контейнер перед перерендерингом
}
// Создаем контейнер для второго рекламного блока, если он не существует
let adContainer = existingAdContainer;
if (!adContainer) {
adContainer = document.createElement('div');
adContainer.id = 'yandex_rtb_R-A-12294791-5';
adContainer.style.marginTop = '20px'; // Добавим отступ для красоты
// Находим элемент кнопок "Previous" и "Next" и вставляем перед ним
const paginationElement = document.querySelector('.pagination-nav');
if (paginationElement) {
paginationElement.parentNode.insertBefore(adContainer, paginationElement);
} else {
// Если кнопок нет, добавляем контейнер в конец body
document.body.appendChild(adContainer);
}
}
// Создаем скрипт для рендеринга рекламы
const script = document.createElement('script');
script.innerHTML = `
window.yaContextCb.push(() => {
Ya.Context.AdvManager.destroy('yandex_rtb_R-A-12294791-5'); // Удаляем предыдущий экземпляр блока
Ya.Context.AdvManager.render({
"blockId": "R-A-12294791-3",
"type": "floorAd",
"platform": "touch"
});
Ya.Context.AdvManager.render({
"blockId": "R-A-12294791-5",
"renderTo": "yandex_rtb_R-A-12294791-5"
});
});
`;
document.body.appendChild(script);
// Удаляем элементы при размонтировании компонента
return () => {
script.remove();
adContainer.innerHTML = ''; // Очищаем контейнер при размонтировании
};
}, [location.pathname]); // Перезапуск эффекта при изменении пути
return (
<>
<Head>
<script>
window.yaContextCb = window.yaContextCb || [];
</script>
<script src="https://yandex.ru/ads/system/context.js" async></script>
</Head>
<Layout {...props} />
</>
);
}