version 3 start

This commit is contained in:
merdan 2025-04-10 15:53:34 +05:00
parent 3028562262
commit 3246e84f96
50 changed files with 199 additions and 1946 deletions

1
.gitignore vendored
View File

@ -30,3 +30,4 @@ _ide_helper.php
.DS_Store
package-lock.json
/node_modules
.qodo

View File

@ -11,7 +11,7 @@ return [
|
*/
'activeTheme' => 'modern',
'activeTheme' => 'modern2',
/*
|--------------------------------------------------------------------------
@ -36,7 +36,7 @@ return [
|
*/
'backendUri' => 'privatecontrolcenter', //howpsuzlyk
'backendUri' => 'backend', //howpsuzlyk
/*
|--------------------------------------------------------------------------
@ -131,7 +131,7 @@ return [
|
*/
'disableCoreUpdates' => false,
'disableCoreUpdates' => true,
/*
|--------------------------------------------------------------------------

View File

@ -1,18 +0,0 @@
<?php namespace AhmadFatoni\ApiGenerator;
use System\Classes\PluginBase;
class Plugin extends PluginBase
{
public $require = [
'RainLab.Builder'
];
public function registerComponents()
{
}
public function registerSettings()
{
}
}

View File

@ -1,50 +0,0 @@
# API Generator
> October CMS plugin to build RESTful APIs.
## Features
- Auto generate routes
- Auto Generate Controller (CRUD)
- Support relationship restful API
## Install
```
composer require AhmadFatoni.ApiGenerator
```
## Usage
### Form
- API Name : Name of your API module
- Base Endpoint : Base endpoint of your API, ex : api/v1/modulename
- Short Description : Describe your API
- Model : select model that will be created API
- Custom Condition : Build customer response using JSON modeling
### Custom Condition Example
```
{
'fillable': 'id,title,content',
'relation': [{
'name': 'user',
'fillable': 'id,first_name'
}, {
'name': 'categories',
'fillable': 'id,name
}]
}
```
* please replace single quote with quote
## Contribute
Pull Requests accepted.
## Contact
You can communicate with me using [linkedin](https://www.linkedin.com/in/ahmad-fatoni)
## License
The OctoberCMS platform is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

View File

@ -1,336 +0,0 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers;
use Backend\Classes\Controller;
use AhmadFatoni\ApiGenerator\Models\ApiGenerator;
use BackendMenu;
use Backend;
use Illuminate\Http\Request;
use Illuminate\Filesystem\Filesystem;
use Redirect;
use Flash;
class ApiGeneratorController extends Controller
{
public $implement = ['Backend\Behaviors\ListController','Backend\Behaviors\FormController','Backend\Behaviors\ReorderController'];
public $listConfig = 'config_list.yaml';
public $formConfig = 'config_form.yaml';
public $reorderConfig = 'config_reorder.yaml';
protected $path = "/api/";
private $homePage = 'ahmadfatoni/apigenerator/apigeneratorcontroller';
protected $files;
public $requiredPermissions = ['ahmadfatoni.apigenerator.manage'];
public function __construct(Filesystem $files)
{
parent::__construct();
BackendMenu::setContext('AhmadFatoni.ApiGenerator', 'api-generator');
$this->files = $files;
}
/**
* delete selected data (multiple delete)
* @return [type] [description]
*/
public function index_onDelete()
{
if (($checkedIds = post('checked')) && is_array($checkedIds) && count($checkedIds)) {
foreach ($checkedIds as $id) {
if ((!$item = ApiGenerator::find($id)))
continue;
$name = $item->name;
if($item->delete()){
$this->deleteApi($name);
}
}
Flash::success('Successfully deleted those data.');
}
return $this->listRefresh();
}
/**
* generate API
* @param Request $request [description]
* @return [type] [description]
*/
public function generateApi(Request $request){
$data['model'] = $request->model;
$modelname = explode("\\", $request->model);
$modelname = $modelname[count($modelname)-1];
$data['modelname'] = $modelname;
$data['controllername'] = str_replace(" ", "", $request->name);
$data['endpoint'] = $request->endpoint;
$data['custom_format'] = $request->custom_format;
if( strpos($data['controllername'], ".") OR strpos($data['controllername'], "/") ){
Flash::success('Failed to create data, invalid API name.');
return Redirect::to( Backend::url($this->homePage));
}
if( isset($request->id) ){
$this->deleteApi($request->oldname, 'false');
}
$this->files->put(__DIR__ . $this->path . $data['controllername'].'Controller.php', $this->compile($data));
$this->files->put(__DIR__ . '/'.'../routes.php', $this->compileRoute($data));
return Redirect::to( Backend::url($this->homePage));
}
/**
* delete available API
* @param [type] $name [description]
* @param [type] $redirect [description]
* @return [type] [description]
*/
public function deleteApi($name, $redirect = null){
$fileLocation = __DIR__ . $this->path.$name;
$fileLocation = str_replace(".", "", $fileLocation);
if( ! file_exists($fileLocation.'Controller.php') ){
Flash::success('Failed to delete data, invalid file location.');
return Redirect::to( Backend::url($this->homePage));
}
if( strpos( strtolower($name), 'apigenerator' ) === false){
$data = [];
//generate new route
$this->files->put(__DIR__ . '/'.'../routes.php', $this->compileRoute($data));
//remove controller
if (file_exists( __DIR__ . $this->path.$name.'Controller.php' )) {
unlink(__DIR__ . $this->path.$name.'Controller.php');
}
if( $redirect != null ){
return 'success without redirect';
}
}
return Redirect::to( Backend::url($this->homePage));
}
public function updateApi($name){
}
/**
* compile controller from template
* @param [type] $data [description]
* @return [type] [description]
*/
public function compile($data){
if( $data['custom_format'] != ''){
$template = $this->files->get(__DIR__ .'/../template/customcontroller.dot');
$template = $this->replaceAttribute($template, $data);
$template = $this->replaceCustomAttribute($template, $data);
}else{
$template = $this->files->get(__DIR__ .'/../template/controller.dot');
$template = $this->replaceAttribute($template, $data);
}
return $template;
}
/**
* replace attribute
* @param [type] $template [description]
* @param [type] $data [description]
* @return [type] [description]
*/
public function replaceAttribute($template, $data){
if( isset( $data['model'] ) ){
$template = str_replace('{{model}}', $data['model'], $template);
}
$template = str_replace('{{modelname}}', $data['modelname'], $template);
$template = str_replace('{{controllername}}', $data['controllername'], $template);
return $template;
}
/**
* replace custom attribute
* @param [type] $template [description]
* @param [type] $data [description]
* @return [type] [description]
*/
public function replaceCustomAttribute($template, $data){
$arr = str_replace('\t', '', $data['custom_format']);
$arr = json_decode($arr);
$select = str_replace('<br />', '', $this->compileOpenIndexFunction($data['modelname'], 'index'));
$show = str_replace('<br />', '', $this->compileOpenIndexFunction($data['modelname'], 'show'));
$fillableParent = '';
if( isset($arr->fillable) AND $arr->fillable != null ) {
$fillableParent = $this->compileFillableParent($arr->fillable);
}
if( isset($arr->relation) AND $arr->relation != null AND is_array($arr->relation) AND count($arr->relation) > 0) {
$select .= str_replace('<br />', '', $this->compileFillableChild($arr->relation));
$show .= str_replace('<br />', '', $this->compileFillableChild($arr->relation));
}
$select .= "->select(".$fillableParent.")";
$show .= "->select(".$fillableParent.")->where('id', '=', \$id)->first();";
( $fillableParent != '') ? $select .= "->get()->toArray();" : $select .= "->toArray();" ;
$closeFunction = str_replace('<br />', '', nl2br(
"
return \$this->helpers->apiArrayResponseBuilder(200, 'success', \$data);
}"));
$select .= $closeFunction;
$show .= $closeFunction;
$template = str_replace('{{select}}', $select, $template);
$template = str_replace('{{show}}', $show, $template);
return $template;
}
public function compileOpenIndexFunction($modelname, $type){
if( $type == 'index'){
return nl2br("
public function index(){
\$data = \$this->".$modelname);
}else{
return nl2br("
public function show(\$id){
\$data = \$this->".$modelname);
}
}
public function compileFillableParent($fillable){
$fillableParentArr = explode(",", $fillable);
$fillableParent = '';
foreach ($fillableParentArr as $key) {
$fillableParent .= ",'".$key."'";
}
$fillableParent = substr_replace($fillableParent, '', 0 , 1);
return $fillableParent;
}
public function compileFillableChild($fillable){
$select = "->with(array(";
foreach ($fillable as $key) {
$fillableChild = "";
if( isset($key->fillable) AND $key->fillable != null ){
$fillableChildArr = explode(",", $key->fillable);
foreach ($fillableChildArr as $key2) {
$fillableChild .= ",'".$key2."'";
}
$fillableChild = substr_replace($fillableChild, '', 0 , 1);
}
$select .= nl2br(
"
'".$key->name."'=>function(\$query){
\$query->select(".$fillableChild.");
},");
}
$select .= " ))";
return $select;
}
public function compileRoute($data){
$oldData = ApiGenerator::all();
$routeList = "";
if( count($oldData) > 0 ){
$routeList .= $this->parseRouteOldData($oldData, $data);
}
if( count($data) > 0 ){
$data['modelname'] = $data['endpoint'];
if( $data['modelname'][0] == "/" ){
$data['modelname'] = substr_replace($data['modelname'], '', 0 , 1);
}
$routeList .= $this->parseRoute($data);
}
$route = $this->files->get(__DIR__ .'/../template/routes.dot');
$route = str_replace('{{route}}', $routeList, $route);
return $route;
}
public function parseRouteOldData($oldData, $data = null){
$routeList = "";
if( count($data) == 0 ) $data['modelname']='';
foreach ( $oldData as $key ) {
$modelname = explode("\\", $key->model);
$modelname = $modelname[count($modelname)-1];
$old['modelname'] = $key->endpoint;
$old['controllername'] = $key->name;
if( $data['modelname'] != $modelname ){
if( $old['modelname'][0] == "/" ){
$old['modelname'] = substr_replace($old['modelname'], '', 0 , 1);
}
$routeList .= $this->parseRoute($old);
}
}
return $routeList;
}
public function parseRoute($data){
$template = $this->files->get(__DIR__ .'/../template/route.dot');
$template = $this->replaceAttribute($template, $data);
return $template;
}
public static function getAfterFilters() {return [];}
public static function getBeforeFilters() {return [];}
public function callAction($method, $parameters=false) {
return call_user_func_array(array($this, $method), $parameters);
}
}

View File

@ -1 +0,0 @@
api controller here

View File

@ -1,18 +0,0 @@
<div data-control="toolbar">
<a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller/create') ?>" class="btn btn-primary oc-icon-plus"><?= e(trans('backend::lang.form.create')) ?></a>
<button
class="btn btn-default oc-icon-trash-o"
disabled="disabled"
onclick="$(this).data('request-data', {
checked: $('.control-list').listWidget('getChecked')
})"
data-request="onDelete"
data-request-confirm="<?= e(trans('backend::lang.list.delete_selected_confirm')) ?>"
data-trigger-action="enable"
data-trigger=".control-list input[type=checkbox]"
data-trigger-condition="checked"
data-request-success="$(this).prop('disabled', true)"
data-stripe-load-indicator>
<?= e(trans('backend::lang.list.delete_selected')) ?>
</button>
</div>

View File

@ -1,3 +0,0 @@
<div data-control="toolbar">
<a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>" class="btn btn-primary oc-icon-caret-left"><?= e(trans('backend::lang.form.return_to_list')) ?></a>
</div>

View File

@ -1,10 +0,0 @@
name: ApiGeneratorController
form: $/ahmadfatoni/apigenerator/models/apigenerator/fields.yaml
modelClass: AhmadFatoni\ApiGenerator\Models\ApiGenerator
defaultRedirect: ahmadfatoni/apigenerator/apigeneratorcontroller
create:
redirect: 'ahmadfatoni/apigenerator/apigeneratorcontroller/update/:id'
redirectClose: ahmadfatoni/apigenerator/apigeneratorcontroller
update:
redirect: ahmadfatoni/apigenerator/apigeneratorcontroller
redirectClose: ahmadfatoni/apigenerator/apigeneratorcontroller

View File

@ -1,11 +0,0 @@
list: $/ahmadfatoni/apigenerator/models/apigenerator/columns.yaml
modelClass: AhmadFatoni\ApiGenerator\Models\ApiGenerator
title: ApiGeneratorController
noRecordsMessage: 'backend::lang.list.no_records'
showSetup: true
showCheckboxes: true
toolbar:
buttons: list_toolbar
search:
prompt: 'backend::lang.list.search_prompt'
recordUrl: 'ahmadfatoni/apigenerator/apigeneratorcontroller/update/:id'

View File

@ -1,4 +0,0 @@
title: ApiGeneratorController
modelClass: AhmadFatoni\ApiGenerator\Models\ApiGenerator
toolbar:
buttons: reorder_toolbar

View File

@ -1,97 +0,0 @@
<?php Block::put('breadcrumb') ?>
<ul>
<li><a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>">ApiListController</a></li>
<li><?= e($this->pageTitle) ?></li>
</ul>
<?php Block::endPut() ?>
<?php if (!$this->fatalError): ?>
<?= Form::open(['class' => 'layout']) ?>
<div class="layout-row">
<?= $this->formRender() ?>
</div>
<div class="modal fade" id="modal-id">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Custom Condition</h4>
</div>
<div class="modal-body">
<?php
$data = '{
"fillable": "id,title,content",
"relation": [{
"name": "user",
"fillable": "id,first_name"
}, {
"name": "categories",
"fillable": "id,name"
}]
}';
echo $data ;
?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="form-buttons">
<div class="loading-indicator-container">
<button
type="submit"
data-request="onSave"
data-request-success="saveData()"
data-hotkey="ctrl+s, cmd+s"
data-load-indicator="<?= e(trans('backend::lang.form.saving')) ?>"
class="btn btn-primary">
<?= e(trans('backend::lang.form.create')) ?>
</button>
<a data-toggle="modal" href='#modal-id'>
<button type="button" class="btn btn-default">
Example Custom Condition
</button>
</a>
<a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>" class="btn btn-warning">Cancel</a>
</div>
</div>
<?= Form::close() ?>
<form method="post" id="generate" accept-charset="utf-8" action="<?= route('fatoni.generate.api') ?>" style="display:none">
<input type='text' name='name' id="name">
<input type='text' name='model' id="model">
<input type='text' name='custom_format' id="custom_format">
<input type='text' name='endpoint' id="endpoint">
<button
type="submit"
class="btn btn-primary" name="send" id="send">
send
</button>
</form>
<?php else: ?>
<p class="flash-message static error"><?= e(trans($this->fatalError)) ?></p>
<p><a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>" class="btn btn-default"><?= e(trans('backend::lang.form.return_to_list')) ?></a></p>
<?php endif ?>
<script type="text/javascript">
function saveData(){
document.getElementById('name').value = document.getElementById('Form-field-ApiGenerator-name').value;
document.getElementById('model').value = document.getElementById('Form-field-ApiGenerator-model').value;
document.getElementById('custom_format').value = document.getElementById('Form-field-ApiGenerator-custom_format').value;
document.getElementById('endpoint').value = document.getElementById('Form-field-ApiGenerator-endpoint').value;
document.getElementById('send').click();
}
</script>

View File

@ -1 +0,0 @@
<?= $this->listRender() ?>

View File

@ -1,22 +0,0 @@
<?php Block::put('breadcrumb') ?>
<ul>
<li><a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>">ApiGeneratorController</a></li>
<li><?= e($this->pageTitle) ?></li>
</ul>
<?php Block::endPut() ?>
<?php if (!$this->fatalError): ?>
<div class="form-preview">
<?= $this->formRenderPreview() ?>
</div>
<?php else: ?>
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
<?php endif ?>
<p>
<a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>" class="btn btn-default oc-icon-chevron-left">
<?= e(trans('backend::lang.form.return_to_list')) ?>
</a>
</p>

View File

@ -1,8 +0,0 @@
<?php Block::put('breadcrumb') ?>
<ul>
<li><a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>">ApiGeneratorController</a></li>
<li><?= e($this->pageTitle) ?></li>
</ul>
<?php Block::endPut() ?>
<?= $this->reorderRender() ?>

View File

@ -1,133 +0,0 @@
<?php Block::put('breadcrumb') ?>
<ul>
<li><a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>">ApiListController</a></li>
<li><?= e($this->pageTitle) ?></li>
</ul>
<?php Block::endPut() ?>
<?php if (!$this->fatalError): ?>
<?= Form::open(['class' => 'layout']) ?>
<div class="layout-row">
<?= $this->formRender() ?>
</div>
<div class="modal fade" id="modal-id">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Custom Condition</h4>
</div>
<div class="modal-body">
<?php
$data = '{
"fillable": "id,title,content",
"relation": [{
"name": "user",
"fillable": "id,first_name"
}, {
"name": "categories",
"fillable": "id,name"
}]
}';
echo $data ;
?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="form-buttons">
<div class="loading-indicator-container">
<button
type="submit"
data-request="onSave"
data-request-success="saveData()"
data-request-data="redirect:0"
data-hotkey="ctrl+s, cmd+s"
data-load-indicator="<?= e(trans('backend::lang.form.saving')) ?>"
class="btn btn-primary">
<?= e(trans('backend::lang.form.save')) ?>
</button>
<a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>" class="btn btn-warning"><div id="cancel">Cancel</div></a>
<button
type="button"
class="oc-icon-trash-o btn-icon danger pull-right"
data-request="onDelete"
data-request-success="delData()"
data-load-indicator="<?= e(trans('backend::lang.form.deleting')) ?>"
data-request-confirm="<?= e(trans('backend::lang.form.confirm_delete')) ?>">
</button>
<a data-toggle="modal" href='#modal-id'>
<button type="button" class="btn btn-default">
Example Custom Condition
</button>
</a>
</div>
</div>
<?= Form::close() ?>
<?php else: ?>
<p class="flash-message static error"><?= e(trans($this->fatalError)) ?></p>
<p><a href="<?= Backend::url('ahmadfatoni/apigenerator/apigeneratorcontroller') ?>" class="btn btn-default"><?= e(trans('backend::lang.form.return_to_list')) ?></a></p>
<?php endif ?>
<form method="get" id="del" style="display:none" action="<?= route('fatoni.delete.api', ['id'=> $this->widget->form->data->attributes['name'] ]) ?>">
<button
type="submit"
class="btn btn-primary" name="send" id="send">
send
</button>
</form>
<form method="post" id="generate" accept-charset="utf-8" action="<?= route('fatoni.generate.api') ?>" style="display:none">
<input type='text' name='id' id="id" value="<?= $this->widget->form->data->attributes['id'] ?>">
<input type='text' name='name' id="name">
<input type='text' name='endpoint' id="endpoint">
<input type='text' name='oldname' id="oldname" value="<?= $this->widget->form->data->attributes['name'] ?>">
<input type='text' name='oldmodel' id="oldmodel" value="<?= $this->widget->form->data->attributes['model'] ?>">
<input type='text' name='oldendpoint' id="oldendpoint" value="<?= $this->widget->form->data->attributes['endpoint'] ?>">
<textarea name='oldcustom_format' id="oldcustom_format"><?= $this->widget->form->data->attributes['custom_format'] ?></textarea>
<input type='text' name='model' id="model">
<input type='text' name='custom_format' id="custom_format">
<button
type="submit"
class="btn btn-primary" name="save" id="save">
send
</button>
</form>
<script type="text/javascript">
function delData(){
document.getElementById('send').click();
}
</script>
<script type="text/javascript">
function saveData(){
document.getElementById('name').value = document.getElementById('Form-field-ApiGenerator-name').value;
document.getElementById('model').value = document.getElementById('Form-field-ApiGenerator-model').value;
document.getElementById('custom_format').value = document.getElementById('Form-field-ApiGenerator-custom_format').value;
document.getElementById('endpoint').value = document.getElementById('Form-field-ApiGenerator-endpoint').value;
if (
document.getElementById('name').value != document.getElementById('oldname').value ||
document.getElementById('Form-field-ApiGenerator-model').value != document.getElementById('oldmodel').value ||
document.getElementById('Form-field-ApiGenerator-custom_format').value != document.getElementById('oldcustom_format').value ||
document.getElementById('Form-field-ApiGenerator-endpoint').value != document.getElementById('oldendpoint').value
){
document.getElementById('save').click();
}else{
document.getElementById('cancel').click();
}
}
</script>

View File

@ -1,6 +0,0 @@
<?php return [
'plugin' => [
'name' => 'API-Generator',
'description' => 'Generate API base on Builder Plugin'
]
];

View File

@ -1,76 +0,0 @@
<?php namespace AhmadFatoni\ApiGenerator\Models;
use Model, Log;
use RainLab\Builder\Classes\ComponentHelper;
/**
* Model
*/
class ApiGenerator extends Model
{
use \October\Rain\Database\Traits\Validation;
/*
* Validation
*/
public $rules = [
'name' => 'required|unique:ahmadfatoni_apigenerator_data,name|regex:/^[\pL\s\-]+$/u',
'endpoint' => 'required|unique:ahmadfatoni_apigenerator_data,endpoint',
'custom_format' => 'json'
];
public $customMessages = [
'custom_format.json' => 'Invalid Json Format Custom Condition'
];
/*
* Disable timestamps by default.
* Remove this line if timestamps are defined in the database table.
*/
public $timestamps = false;
/**
* @var string The database table used by the model.
*/
public $table = 'ahmadfatoni_apigenerator_data';
/**
* get model List
* @return [type] [description]
*/
public function getModelOptions(){
return ComponentHelper::instance()->listGlobalModels();
}
/**
* [setCustomFormatAttribute description]
* @param [type] $value [description]
*/
public function setCustomFormatAttribute($value){
$json = str_replace('\t', '', $value);
$json = json_decode($json);
if( $json != null){
if( ! isset($json->fillable) AND ! isset($json->relation) ){
return $this->attributes['custom_format'] = 'invalid format';
}
if( isset($json->relation) AND $json->relation != null ){
foreach ($json->relation as $key) {
if( !isset($key->name) OR $key->name == null ){
return $this->attributes['custom_format'] = 'invalid format';
}
}
}
}
return $this->attributes['custom_format'] = $value;
}
}

View File

@ -1,9 +0,0 @@
columns:
name:
label: 'API NAME'
type: text
searchable: true
sortable: true
endpoint:
label: 'BASE ENDPOINT'
type: text

View File

@ -1,33 +0,0 @@
fields:
name:
label: 'API Name'
oc.commentPosition: ''
span: auto
placeholder: 'Name of your API'
required: 1
type: text
endpoint:
label: 'Base Endpoint'
oc.commentPosition: ''
span: auto
placeholder: api/v1/modulename
required: 1
type: text
description:
label: 'Short Description'
oc.commentPosition: ''
span: auto
placeholder: 'Descript your API'
type: text
model:
label: 'Select Model'
oc.commentPosition: ''
span: auto
required: 1
type: dropdown
custom_format:
label: 'Custom Condition (Fillable and Relation)'
size: large
oc.commentPosition: ''
span: full
type: textarea

View File

@ -1,17 +0,0 @@
plugin:
name: 'ahmadfatoni.apigenerator::lang.plugin.name'
description: 'ahmadfatoni.apigenerator::lang.plugin.description'
author: AhmadFatoni
icon: oc-icon-bolt
homepage: ''
#navigation:
# api-generator:
# label: 'API Generator'
# url: ahmadfatoni/apigenerator/apigeneratorcontroller
# icon: icon-cogs
# permissions:
# - ahmadfatoni.apigenerator.manage
permissions:
ahmadfatoni.apigenerator.manage:
tab: 'API Generator'
label: 'Manage the API Generator'

View File

@ -1,21 +0,0 @@
<?php
Route::post('fatoni/generate/api', array('as' => 'fatoni.generate.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@generateApi'));
Route::post('fatoni/update/api/{id}', array('as' => 'fatoni.update.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@updateApi'));
Route::get('fatoni/delete/api/{id}', array('as' => 'fatoni.delete.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@deleteApi'));
//postlar bilen categorialar
Route::resource('api/categories', 'AhmadFatoni\ApiGenerator\Controllers\API\CategoriesController', ['except' => ['destroy', 'create', 'edit']]);
Route::resource('api/advetisements', 'AhmadFatoni\ApiGenerator\Controllers\API\AdvertisementsController', ['except' => ['destroy', 'create', 'edit']]);
Route::get('api/group/advertisements', 'AhmadFatoni\ApiGenerator\Controllers\API\AdvertisementsController@getByGroup');
Route::resource('{locale}/api/posts', 'AhmadFatoni\ApiGenerator\Controllers\API\postsController', ['except' => ['destroy', 'create', 'edit']]);
Route::get('api/v2/categories', 'AhmadFatoni\ApiGenerator\Controllers\API\CategoriesV2Controller@index');
Route::get('api/v2/media', 'AhmadFatoni\ApiGenerator\Controllers\API\MediaController@index');
//Route::get('api/v2/afisha', 'AhmadFatoni\ApiGenerator\Controllers\API\AfishaController@index');
Route::resource('api/v2/afisha', 'AhmadFatoni\ApiGenerator\Controllers\API\AfishaController', ['except' => ['destroy', 'create', 'edit']]);
Route::get('api/version',function (){
return '2.0.8';
});

View File

@ -1,99 +0,0 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
use Cms\Classes\Controller;
use BackendMenu;
use Illuminate\Http\Request;
use AhmadFatoni\ApiGenerator\Helpers\Helpers;
use Illuminate\Support\Facades\Validator;
use {{model}};
class {{controllername}}Controller extends Controller
{
protected ${{modelname}};
protected $helpers;
public function __construct({{modelname}} ${{modelname}}, Helpers $helpers)
{
parent::__construct();
$this->{{modelname}} = ${{modelname}};
$this->helpers = $helpers;
}
public function index(){
$data = $this->{{modelname}}->all()->toArray();
return $this->helpers->apiArrayResponseBuilder(200, 'success', $data);
}
public function show($id){
$data = $this->{{modelname}}::find($id);
if ($data){
return $this->helpers->apiArrayResponseBuilder(200, 'success', [$data]);
} else {
$this->helpers->apiArrayResponseBuilder(404, 'not found', ['error' => 'Resource id=' . $id . ' could not be found']);
}
}
public function store(Request $request){
$arr = $request->all();
while ( $data = current($arr)) {
$this->{{modelname}}->{key($arr)} = $data;
next($arr);
}
$validation = Validator::make($request->all(), $this->{{modelname}}->rules);
if( $validation->passes() ){
$this->{{modelname}}->save();
return $this->helpers->apiArrayResponseBuilder(201, 'created', ['id' => $this->{{modelname}}->id]);
}else{
return $this->helpers->apiArrayResponseBuilder(400, 'fail', $validation->errors() );
}
}
public function update($id, Request $request){
$status = $this->{{modelname}}->where('id',$id)->update($data);
if( $status ){
return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been updated successfully.');
}else{
return $this->helpers->apiArrayResponseBuilder(400, 'bad request', 'Error, data failed to update.');
}
}
public function delete($id){
$this->{{modelname}}->where('id',$id)->delete();
return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been deleted successfully.');
}
public function destroy($id){
$this->{{modelname}}->where('id',$id)->delete();
return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been deleted successfully.');
}
public static function getAfterFilters() {return [];}
public static function getBeforeFilters() {return [];}
public static function getMiddleware() {return [];}
public function callAction($method, $parameters=false) {
return call_user_func_array(array($this, $method), $parameters);
}
}

View File

@ -1,35 +0,0 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
use Cms\Classes\Controller;
use BackendMenu;
use Illuminate\Http\Request;
use {{model}};
class ApiListController extends Controller
{
protected ${{modelname}};
public function __construct({{modelname}} ${{modelname}})
{
parent::__construct();
$this->{{modelname}} = ${{modelname}};
}
public static function getAfterFilters() {return [];}
public static function getBeforeFilters() {return [];}
public static function getMiddleware() {return [];}
public function callAction($method, $parameters=false) {
return call_user_func_array(array($this, $method), $parameters);
}
// public function create(Request $request){
// $arr = $request->all();
// while ( $data = current($arr)) {
// $this->
// }
// return json_encode($this->{{modelname}}->store($request));
// }
}

View File

@ -1,83 +0,0 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
use Cms\Classes\Controller;
use BackendMenu;
use Illuminate\Http\Request;
use AhmadFatoni\ApiGenerator\Helpers\Helpers;
use {{model}};
class {{controllername}}Controller extends Controller
{
protected ${{modelname}};
protected $helpers;
public function __construct({{modelname}} ${{modelname}}, Helpers $helpers)
{
parent::__construct();
$this->{{modelname}} = ${{modelname}};
$this->helpers = $helpers;
}
{{select}}
{{show}}
public function store(Request $request){
$arr = $request->all();
while ( $data = current($arr)) {
$this->{{modelname}}->{key($arr)} = $data;
next($arr);
}
$validation = Validator::make($request->all(), $this->{{modelname}}->rules);
if( $validation->passes() ){
$this->{{modelname}}->save();
return $this->helpers->apiArrayResponseBuilder(201, 'created', ['id' => $this->{{modelname}}->id]);
}else{
return $this->helpers->apiArrayResponseBuilder(400, 'fail', $validation->errors() );
}
}
public function update($id, Request $request){
$status = $this->{{modelname}}->where('id',$id)->update($data);
if( $status ){
return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been updated successfully.');
}else{
return $this->helpers->apiArrayResponseBuilder(400, 'bad request', 'Error, data failed to update.');
}
}
public function delete($id){
$this->{{modelname}}->where('id',$id)->delete();
return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been deleted successfully.');
}
public function destroy($id){
$this->{{modelname}}->where('id',$id)->delete();
return $this->helpers->apiArrayResponseBuilder(200, 'success', 'Data has been deleted successfully.');
}
public static function getAfterFilters() {return [];}
public static function getBeforeFilters() {return [];}
public static function getMiddleware() {return [];}
public function callAction($method, $parameters=false) {
return call_user_func_array(array($this, $method), $parameters);
}
}

View File

@ -1,3 +0,0 @@
Route::resource('{{modelname}}', 'AhmadFatoni\ApiGenerator\Controllers\API\{{controllername}}Controller', ['except' => ['destroy', 'create', 'edit']]);
Route::get('{{modelname}}/{id}/delete', ['as' => '{{modelname}}.delete', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\API\{{controllername}}Controller@destroy']);

View File

@ -1,12 +0,0 @@
<?php
Route::post('fatoni/generate/api', array('as' => 'fatoni.generate.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@generateApi'));
Route::post('fatoni/update/api/{id}', array('as' => 'fatoni.update.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@updateApi'));
Route::get('fatoni/delete/api/{id}', array('as' => 'fatoni.delete.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@deleteApi'));
//postlar bilen categorialar
Route::resource('api/categories', 'AhmadFatoni\ApiGenerator\Controllers\API\CategoriesController', ['except' => ['destroy', 'create', 'edit']]);
Route::resource('{locale}/api/posts', 'AhmadFatoni\ApiGenerator\Controllers\API\postsController', ['except' => ['destroy', 'create', 'edit']]);
Route::get('api/version',function (){
return '2.0.8';
});
{{route}}

View File

@ -1,26 +0,0 @@
<?php namespace AhmadFatoni\ApiGenerator\Updates;
use Schema;
use October\Rain\Database\Updates\Migration;
class BuilderTableCreateAhmadfatoniApigeneratorData extends Migration
{
public function up()
{
Schema::create('ahmadfatoni_apigenerator_data', function($table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->string('endpoint');
$table->string('model');
$table->string('description')->nullable();
$table->text('custom_format')->nullable();
});
}
public function down()
{
Schema::dropIfExists('ahmadfatoni_apigenerator_data');
}
}

View File

@ -1,15 +0,0 @@
1.0.1:
- 'Initialize plugin.'
1.0.2:
- 'Database implementation'
1.0.3:
- 'add builder plugin on requirements dependency'
- builder_table_create_ahmadfatoni_apigenerator_data.php
1.0.4:
- 'fixing bug on PHP 7'
1.0.5:
- 'fixing bug on request delete data'
1.0.6:
- 'fixing bug on generate endpoint'
1.0.7:
- 'fixing bug on October CMS v1.0.456'

View File

@ -1,12 +1,10 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
<?php namespace Tps\Tps\Controllers\API;
use Cms\Classes\Controller;
use BackendMenu;
use DB;
use Config;
use Illuminate\Http\Request;
use AhmadFatoni\ApiGenerator\Helpers\Helpers;
use Illuminate\Support\Facades\Validator;
use Tps\Reklama\Models\Reklama;
use Tps\Reklama\Models\Statistika;
use Carbon\Carbon;

View File

@ -1,12 +1,7 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
<?php namespace Tps\Tps\Controllers\API;
use Cms\Classes\Controller;
use BackendMenu;
use DB;
use Config;
use Illuminate\Http\Request;
use AhmadFatoni\ApiGenerator\Helpers\Helpers;
use Illuminate\Support\Facades\Validator;
use Tps\Tps\Models\Afisha;
class AfishaController extends Controller

View File

@ -1,11 +1,8 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
<?php namespace Tps\Tps\Controllers\API;
use Cms\Classes\Controller;
use BackendMenu;
use Illuminate\Http\Request;
use AhmadFatoni\ApiGenerator\Helpers\Helpers;
use Illuminate\Support\Facades\Validator;
use RainLab\Blog\Models\Category;
class CategoriesController extends Controller
{

View File

@ -1,12 +1,7 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
<?php namespace Tps\Tps\Controllers\API;
use Cms\Classes\Controller;
use BackendMenu;
use DB;
use Config;
use Illuminate\Http\Request;
use AhmadFatoni\ApiGenerator\Helpers\Helpers;
use Illuminate\Support\Facades\Validator;
use RainLab\Blog\Models\CategoryGroup;
use RainLab\Blog\Models\Post;
class CategoriesV2Controller extends Controller

View File

@ -1,12 +1,8 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
<?php namespace Tps\Tps\Controllers\API;
use Cms\Classes\Controller;
use BackendMenu;
use DB;
use Config;
use Illuminate\Http\Request;
use AhmadFatoni\ApiGenerator\Helpers\Helpers;
use Illuminate\Support\Facades\Validator;
use Tps\Tps\Models\Media;
class MediaController extends Controller

View File

@ -1,14 +1,11 @@
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
<?php namespace Tps\Tps\Controllers\API;
use Cms\Classes\Controller;
use BackendMenu;
use DB;
use Config;
use Illuminate\Http\Request;
use AhmadFatoni\ApiGenerator\Helpers\Helpers;
use Illuminate\Support\Facades\Validator;
use RainLab\Blog\Models\Post;
class postsController extends Controller
class PostController extends Controller
{
protected $Post;

View File

@ -1,4 +1,4 @@
<?php namespace AhmadFatoni\ApiGenerator\Helpers;
<?php namespace Tps\Tps\Helpers;
Class Helpers {

View File

@ -4,4 +4,23 @@ use Tps\Tps\Controllers\TestQuestion;
// Custom Routes
Route::get('{locale}/test/questions/{id}', 'Tps\Tps\Controllers\TestQuestion@getQuestions');
Route::get('{locale}/test/questions/{id}', 'Tps\Tps\Controllers\TestQuestion@getQuestions');
Route::post('fatoni/generate/api', array('as' => 'fatoni.generate.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@generateApi'));
Route::post('fatoni/update/api/{id}', array('as' => 'fatoni.update.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@updateApi'));
Route::get('fatoni/delete/api/{id}', array('as' => 'fatoni.delete.api', 'uses' => 'AhmadFatoni\ApiGenerator\Controllers\ApiGeneratorController@deleteApi'));
//postlar bilen categorialar
Route::resource('api/categories', 'AhmadFatoni\ApiGenerator\Controllers\API\CategoriesController', ['except' => ['destroy', 'create', 'edit']]);
Route::resource('api/advetisements', 'AhmadFatoni\ApiGenerator\Controllers\API\AdvertisementsController', ['except' => ['destroy', 'create', 'edit']]);
Route::get('api/group/advertisements', 'AhmadFatoni\ApiGenerator\Controllers\API\AdvertisementsController@getByGroup');
Route::resource('{locale}/api/posts', 'AhmadFatoni\ApiGenerator\Controllers\API\postsController', ['except' => ['destroy', 'create', 'edit']]);
Route::get('api/v2/categories', 'AhmadFatoni\ApiGenerator\Controllers\API\CategoriesV2Controller@index');
Route::get('api/v2/media', 'AhmadFatoni\ApiGenerator\Controllers\API\MediaController@index');
//Route::get('api/v2/afisha', 'AhmadFatoni\ApiGenerator\Controllers\API\AfishaController@index');
Route::resource('api/v2/afisha', 'AhmadFatoni\ApiGenerator\Controllers\API\AfishaController', ['except' => ['destroy', 'create', 'edit']]);
Route::get('api/version',function (){
return '2.0.8';
});

View File

@ -8,52 +8,10 @@
$uri = urldecode(
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
);
/**
* October - The PHP platform that gets back to basics.
*
* @package October
* @author Alexey Bobkov, Samuel Georges
*/
/*
|--------------------------------------------------------------------------
| Register composer
|--------------------------------------------------------------------------
|
| Composer provides a generated class loader for the application.
|
*/
require __DIR__.'/bootstrap/autoload.php';
/*
|--------------------------------------------------------------------------
| Load framework
|--------------------------------------------------------------------------
|
| This загружает фреймворк и инициализирует приложение.
|
*/
$app = require_once __DIR__.'/bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Process request
|--------------------------------------------------------------------------
|
| Выполняем запрос и отправляем ответ клиенту.
|
*/
$kernel = $app->make('Illuminate\Contracts\Http\Kernel');
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
$kernel->terminate($request, $response);
// This file allows us to emulate Apache's "mod_rewrite" functionality from the
// built-in PHP web server. This provides a convenient way to test a Laravel
// application without having installed a "real" web server software here.
if ($uri !== '/' && file_exists(__DIR__.'/'.$uri)) {
return false;
}
require_once __DIR__.'/index.php';

View File

@ -0,0 +1,30 @@
<?php return array (
'laravel/scout' =>
array (
'providers' =>
array (
0 => 'Laravel\\Scout\\ScoutServiceProvider',
),
),
'laravel/tinker' =>
array (
'providers' =>
array (
0 => 'Laravel\\Tinker\\TinkerServiceProvider',
),
),
'meilisearch/meilisearch-laravel-scout' =>
array (
'providers' =>
array (
0 => 'Meilisearch\\Scout\\MeilisearchServiceProvider',
),
),
'nesbot/carbon' =>
array (
'providers' =>
array (
0 => 'Carbon\\Laravel\\ServiceProvider',
),
),
);

View File

@ -1,15 +0,0 @@
<?php namespace TestVendor\Goto;
use System\Classes\PluginBase;
class Plugin extends PluginBase
{
public function pluginDetails()
{
return [
'name' => 'Invalid Test Plugin',
'description' => 'Test plugin used by unit tests to detect plugins with invalid namespaces.',
'author' => 'Test Vendor'
];
}
}

View File

@ -1,25 +0,0 @@
<?php namespace TestVendor\Test;
use System\Classes\PluginBase;
class Plugin extends PluginBase
{
public function pluginDetails()
{
return [
'name' => 'Another Test Plugin',
'description' => 'Test plugin used by unit tests with the same name.',
'author' => 'Test Vendor'
];
}
public function registerFormWidgets()
{
return [
'TestVendor\Test\FormWidgets\Sample' => [
'label' => 'Sample',
'code' => 'sample'
]
];
}
}

View File

@ -1,7 +0,0 @@
<?php namespace TestVendor\Test\FormWidgets;
use Backend\Classes\FormWidgetBase;
class Sample extends FormWidgetBase
{
}

View File

@ -46,18 +46,6 @@ $this['canonical'] = 'https://orient.tm/'.request()->path();
</head>
<body>
<script async type="application/javascript"
src="https://news.google.com/swg/js/v1/swg-basic.js"></script>
<script>
(self.SWG_BASIC = self.SWG_BASIC || []).push( basicSubscriptions => {
basicSubscriptions.init({
type: "NewsArticle",
isPartOfType: ["Product"],
isPartOfProductId: "CAowwqzaCw:openaccess",
clientOptions: { theme: "light", lang: "ru" },
});
});
</script>
{% partial 'new/mobile-search' %}
<section class="big-banner">
@ -149,8 +137,8 @@ $this['canonical'] = 'https://orient.tm/'.request()->path();
{% partial 'new/footer' %}
<script src="{{ 'assets/new/jquery.js'|theme}}"></script>
<script src="{{ 'assets/new/scripts/swiper/swiper-bundle.min.js'|theme}}"></script>
<script src="{{ 'assets/new/copy.js'|theme}}"></script>
<script src="{{ 'assets/new/copy.js'|theme}}"></script>
{% framework extras %}
@ -169,6 +157,18 @@ $this['canonical'] = 'https://orient.tm/'.request()->path();
gtag('config', 'G-HHRB3PCSBQ');
</script>
<script async type="application/javascript"
src="https://news.google.com/swg/js/v1/swg-basic.js"></script>
<script>
(self.SWG_BASIC = self.SWG_BASIC || []).push( basicSubscriptions => {
basicSubscriptions.init({
type: "NewsArticle",
isPartOfType: ["Product"],
isPartOfProductId: "CAowwqzaCw:openaccess",
clientOptions: { theme: "light", lang: "ru" },
});
});
</script>
</body>

View File

@ -0,0 +1,105 @@
title = "Media"
url = "/media/:slug?"
layout = "new/master-inside"
description = "media materials"
is_hidden = 0
robot_index = "index"
robot_follow = "follow"
==
<?php
function onStart(){
if($this['categorySlug']){
$this['mediaPostsFilter'] = Tps\Tps\Models\Media::where('type', $this['categorySlug'])->orderBy('published_at', 'DESC')
//->with(['media_view' ])
->withCount(['media_view AS view' => function ($query) {
$query->select(DB::raw("SUM(view) as media_view"));
}
])
->paginate(9);
}else{
$this['mediaPostsFilter'] = Tps\Tps\Models\Media::orderBy('published_at', 'DESC')->paginate(9);
}
}
?>
==
<!-- HEAD end ======== -->
<main class="rubric-main">
<div class="container">
<div class="rubric-inner">
<div class="trending-head">
<h2 style="text-transform: capitalize;">{{'Media'|_}}</h2>
<span></span>
</div>
<div class="video-main-top {% if categorySlug == 'photo' %} photo-main-top {% endif %}">
{% for post in mediaPostsFilter %}
{% if post.type == 'photo' %}
{% partial 'newHome/photo-item' post=post %}
{% else %}
{% partial 'newHome/video-item' post=post %}
{% endif %}
{% else %}
<li class="no-data">{{ 'no Records' }}</li>
{% endfor %}
</div>
{% partial 'new/pagination' items = mediaPostsFilter %}
</div>
</div>
</main>
<section class="photo-scroller">
<div class="photo-scroller-inner">
<div class="swiper photoScrollerSwiper">
<div class="swiper-wrapper">
</div>
<div class="photo-scroller-prev video-prev">
<img src="{{'assets/new/icons/arrow-left-white.svg'|theme}}" alt="" />
</div>
<div class="photo-scroller-next video-next">
<img src="{{'assets/new/icons/arrow-right-white.svg'|theme}}" alt="" />
</div>
</div>
<div class="photo-scroller-closer">
<img src="{{'assets/new/icons/close.svg'|theme}}" alt="" />
</div>
</div>
</section>
<main class="rubric-main">
<div class="container">
<div class="rubric-inner">
<div class="modal" id="expertFormModal">
<div class="modal-content">
<h2 id="form-header">{{'Спроси эксперта'|_}}</h2>
{% component 'expertForm' %}
</div>
</div>
</div>
</div>
</main>
{% put scripts %}
<script>
function countView(id) {
$(this).request('onCountView', {
data: { mediaId: id },
success: function (data) {
// var data = JSON.parse(data);
console.log(data.result);
$('#media_view_'+id).html(data.result);
}
});
};
</script>
{% endput %}

View File

@ -1,39 +0,0 @@
title = "Рубрика Афиша"
url = "/new/afisha/:slug"
layout = "new/master-inside"
is_hidden = 0
robot_index = "index"
robot_follow = "follow"
[blogPosts]
pageNumber = "{{ :page }}"
categoryFilter = "{{ :slug }}"
postsPerPage = 10
noPostsMessage = "No posts found"
sortOrder = "published_at desc"
categoryPage = 404
postPage = 404
==
<main class="affiche">
<div class="container">
<div class="affiche-inner">
<div class="trending-head affiche-head">
<h2>Афиша</h2>
<span></span>
</div>
<div class="rubric-items affiche-items">
{% for post in blogPosts.posts %}
{% partial 'new/afisha-item' post = post %}
{% else %}
<p>No posts found</p>
{% endfor %}
</div>
{% partial 'new/pagination' items = blogPosts.posts %}
</div>
</div>
</main>

View File

@ -1,418 +0,0 @@
title = "new/contact"
url = "/new/contact"
layout = "new/master-inside"
meta_title = "Обратная связь"
is_hidden = 1
robot_index = "index"
robot_follow = "follow"
[contactForm]
==
<style>
/* General Styles */
.contant {
font-family: Roboto, sans-serif;
color: #181D17;
}
.container {
max-width: 1660px;
margin: 0 auto;
padding: 20px;
}
.contact-inner {
display: flex;
flex-direction: column;
gap: 48px
}
.section-title-wrapper {
display: flex;
gap: 16px;
align-items: center;
}
.section-title {
font-family: Roboto;
font-size: 24px;
font-weight: 600;
line-height: 28.13px;
}
.section-title-separator {
width: 100%;
height: 1px;
background: #039F37;
}
.contact-content-wrapper {
display: flex;
gap: 48px;
padding: 0 67px;
}
.contact-left,
.contact-right {
flex: 1;
background: #EBEFE6;
border: 1px solid #E4E9DD;
padding: 24px;
border-radius: 4px;
}
.contact-header {
display: flex;
flex-direction: column;
gap: 16px;
}
.contact-header h3 {
font-size: 20px;
font-weight: 600;
line-height: 23.44px;
}
.contact-header p {
font-size: 17px;
font-weight: 400;
line-height: 22.1px;
color: #424940;
}
.contact-block {
display: flex;
flex-direction: column;
gap: 16px;
max-width: none;
}
.contact-head h2 {
font-size: 24px;
font-weight: bold;
margin-bottom: 15px;
color: #333;
}
.contact-form .contact-content {
display: flex;
flex-direction: column;
gap: 24px;
}
.contact-content-form-top {
display: flex;
gap: 16px;
width: 100%;
}
.contact-form label {
display: block;
font-weight: bold;
font-size: 14px;
color: #333;
}
.contact-form input,
.contact-form textarea {
width: 100%;
padding: 16px;
font-family: Roboto;
font-size: 16px;
font-weight: 400;
line-height: 18.75px;
border: 1px solid #7A7A7A;
border-radius: 2px;
background: none;
}
.contact-form textarea {
resize: none;
}
.contact-antispam img {
max-width: 100%;
border: 1px solid #ccc;
border-radius: 4px;
}
.contact-form button {
display: inline-block;
padding: 10px 20px;
font-size: 20px;
font-weight: 500;
line-height: 23.44px;
background-color: #00822C;
color: #fff;
border: none;
border-radius: 2px;
cursor: pointer;
width: 100%;
max-width: none;
}
.contact-form button:hover {
background-color: #218838;
}
/* Contact Details Section */
.contact-right {
display: flex;
flex-direction: column;
gap: 63px;
}
.contact-right-block-wrapper {
display: flex;
gap: 24px;
}
.contact-right-block {
display: flex;
flex-direction: column;
gap: 24px;
flex: 1;
}
.contact-right-block-title {
font-size: 20px;
font-weight: 400;
line-height: 24px;
}
.contact-right-block-item {
display: flex;
gap: 10px;
}
.contact-right-block-item-content {
display: flex;
flex-direction: column;
}
.contact-right-block-item h4 {
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: #181D17;
}
.contact-right-block-item p {
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: #424940;
}
.contact-right ul {
list-style: none;
padding: 0;
}
.contact-right ul li {
margin-bottom: 10px;
font-size: 14px;
color: #555;
}
.contact-right ul li strong {
color: #333;
}
/* Responsive Styles */
@media (max-width: 768px) {
.contact-inner {
flex-direction: column;
gap: 48px;
}
.contact-content-form-top {
flex-direction: column;
}
.contact-right-block-wrapper {
flex-direction: column;
}
.contact-left,
.contact-right {
flex: unset;
}
.contact-content-wrapper {
padding: 0;
flex-direction: column;
}
.contact-left,
.contact-right {
padding: 16px;
}
}
</style>
<main class="contant">
<div class="container">
<div class="contact-inner">
<!-- Left Section: Contact Form -->
<div class="section-title-wrapper">
<h2 class="section-title">Контакты</h2>
<div class="section-title-separator"></div>
</div>
<div class="contact-content-wrapper">
<div class="contact-left">
<form class="contact-form">
<div class="contact-content">
<div class="contact-header">
<h3>Свяжитесь с нами</h3>
<p>Есть идея или сообщение для нашего агентства? Заполните форму ниже, и мы обязательно с вами свяжемся. Ваши предложения и вопросы помогают нам становиться лучше!</p>
</div>
<div class="contact-content-form-top">
<div class="contact-block">
<label for="name" name="name">Ваше имя <span>*</span> </label>
<input
type="text"
required
placeholder="Аманов Аман"
id="name"
/>
</div>
<div class="contact-block">
<label for="email" name="email"
>Ваше Email <span>*</span>
</label>
<input
required
type="email"
placeholder="amanamanov@gmail.com"
id="email"
/>
</div>
</div>
<div class="contact-block">
<label for="message" name="message">Ваше сообщение</label>
<textarea
name="message"
id="message"
rows="4"
placeholder="Задайте нам вопрос или напишите нам сообщение"
></textarea>
</div>
<button type="submit">Отправить</button>
</div>
</form>
</div>
<div class="contact-right">
<div class="contact-header">
<h3>Контактные данные Orient</h2>
<p>
Наши контактные данные, адрес офиса и режим работы. Мы всегда на
связи, чтобы ответить на ваши вопросы и предложения. Ждем вас!
</p>
</div>
<div class="contact-right-block-wrapper">
<div class="contact-right-block">
<h4 class="contact-right-block-title">Офис расположен по адресу:</h4>
<div class="contact-right-block-item">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 19C9.65 17.2667 7.896 15.5833 6.738 13.95C5.58 12.3167 5.00067 10.7167 5 9.15C5 7.06667 5.65 5.35433 6.95 4.013C8.25 2.67167 9.93333 2.00067 12 2C14.0667 1.99933 15.75 2.67033 17.05 4.013C18.35 5.35567 19 7.068 19 9.15C19 10.7167 18.421 12.3167 17.263 13.95C16.105 15.5833 14.3507 17.2667 12 19ZM12 11C12.55 11 13.021 10.8043 13.413 10.413C13.805 10.0217 14.0007 9.55067 14 9C13.9993 8.44933 13.8037 7.97867 13.413 7.588C13.0223 7.19733 12.5513 7.00133 12 7C11.4487 6.99867 10.978 7.19467 10.588 7.588C10.198 7.98133 10.002 8.452 10 9C9.998 9.548 10.194 10.019 10.588 10.413C10.982 10.807 11.4527 11.0027 12 11ZM5 22V20H19V22H5Z" fill="#39693B"/>
</svg>
<div class="contact-right-block-item-content">
<p>{{ this.theme.officeIsLocated }}</p>
</div>
</div>
</div>
<div class="contact-right-block">
<h4 class="contact-right-block-title">Режим работы:</h4>
<div class="contact-right-block-item">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.55 16.55L15.95 15.125L13 12.175V8H11V13L14.55 16.55ZM11 6H13V4H11V6ZM18 13H20V11H18V13ZM11 20H13V18H11V20ZM4 13H6V11H4V13ZM12 22C10.6167 22 9.31667 21.7373 8.1 21.212C6.88334 20.6867 5.825 19.9743 4.925 19.075C4.025 18.1757 3.31267 17.1173 2.788 15.9C2.26333 14.6827 2.00067 13.3827 2 12C1.99933 10.6173 2.262 9.31733 2.788 8.1C3.314 6.88267 4.02633 5.82433 4.925 4.925C5.82367 4.02567 6.882 3.31333 8.1 2.788C9.318 2.26267 10.618 2 12 2C13.382 2 14.682 2.26267 15.9 2.788C17.118 3.31333 18.1763 4.02567 19.075 4.925C19.9737 5.82433 20.6863 6.88267 21.213 8.1C21.7397 9.31733 22.002 10.6173 22 12C21.998 13.3827 21.7353 14.6827 21.212 15.9C20.6887 17.1173 19.9763 18.1757 19.075 19.075C18.1737 19.9743 17.1153 20.687 15.9 21.213C14.6847 21.739 13.3847 22.0013 12 22Z" fill="#39693B"/>
</svg>
<div class="contact-right-block-item-content">
<p>{{ this.theme.workingHours }}</p>
</div>
</div>
</div>
</div>
<div class="contact-right-block-wrapper">
<div class="contact-right-block">
<h4 class="contact-right-block-title">Контакты редакции:</h4>
<div class="contact-right-block-item">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 20V4H22V20H2ZM12 13L20 8V6L12 11L4 6V8L12 13Z" fill="#39693B"/>
</svg>
<div class="contact-right-block-item-content">
<h4>Email редакции:</h4>
<p>{{ this.theme.editorialEmail }}</p>
</div>
</div>
<div class="contact-right-block-item">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 20H14V19H10V20ZM5 23V1H19V23H5ZM7 16H17V6H7V16Z" fill="#39693B"/>
</svg>
<div class="contact-right-block-item-content">
<h4>Телефон редакции:</h4>
<p>{{ this.theme.editorialPhone }}</p>
</div>
</div>
</div>
<div class="contact-right-block">
<h4 class="contact-right-block-title">Контакты администрации:</h4>
<div class="contact-right-block-item">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 20V4H22V20H2ZM12 13L20 8V6L12 11L4 6V8L12 13Z" fill="#39693B"/>
</svg>
<div class="contact-right-block-item-content">
<h4>Email администрации:</h4>
<p>{{ this.theme.emailTheAdministration }}</p>
</div>
</div>
<div class="contact-right-block-item">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 20H14V19H10V20ZM5 23V1H19V23H5ZM7 16H17V6H7V16Z" fill="#39693B"/>
</svg>
<div class="contact-right-block-item-content">
<h4>Телефон администрации:</h4>
<p>{{ this.theme.administrationPhone }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
{% put scripts %}
<script src="{{ 'assets/new/scripts/marquee/marquee3k.js'|theme }}"></script>
<script src="{{ 'assets/new/scripts/core/main.js'|theme }}"></script>
{% endput %}

View File

@ -1,164 +0,0 @@
title = "new/contact_test"
url = "/new/contact_test"
layout = "new/master-inside"
is_hidden = 1
robot_index = "index"
robot_follow = "follow"
==
<style>
.contact-inner{
gap: 0 !important;
padding: 0 !important;
}
.contacts {
margin: auto !important;
padding: 20px;
}
.contacts-items{
display: flex;
justify-content: space-around;
padding-top: 40px;
flex-wrap: wrap;
}
.contacts h2 {
font-size: 24px;
font-weight: bold;
color: #333;
margin-bottom: 15px;
text-align: center;
}
.contacts p {
font-size: 16px;
color: #555;
line-height: 1.6;
margin: 10px 0;
display: flex;
flex-direction: column;
align-items: center;
width: 70%;
text-align: center;
margin: auto;
}
.contacts p strong {
color: #333;
}
.contacts a {
text-decoration: none;
}
.contacts-item {
width: 200px;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 15px;
}
@media (max-width: 768px) {
.contacts-items {
flex-direction: column;
align-items: center;
padding-top: 20px;
}
.contacts-item {
width: 90%;
margin-bottom: 20px;
}
.contacts h2 {
font-size: 20px;
}
.contacts p {
font-size: 14px;
width: 90%;
}
}
</style>
<main class="contant">
<div class="container">
<div class="contact-inner">
<div class="contacts">
<h2>Контакты</h2>
<p>Свяжитесь с нами удобным для вас способом! Ниже вы найдете наши контакты или можете заполнить форму, чтобы оставить свои предложения и комментарии. Мы всегда рады вашему мнению!</p>
<div class="contacts-items">
<div class="contacts-item">
<span class="contacts-icon"><img src="{{ 'assets/new/images/insta.png'|theme}}" alt="" /></span>
<p><strong>Инстаграм:</strong>{{ this.theme.instagram }}</p>
</div>
<div class="contacts-item">
<span class="contacts-icon"><img src="{{ 'assets/new/images/email.png'|theme}}" alt="" /></span>
<p><strong>Email:</strong> <a href="mailto:example@example.com">{{ this.theme.eMail }}</a></p>
</div>
<div class="contacts-item">
<span class="contacts-icon"><img src="{{ 'assets/new/images/phone.png'|theme}}" alt="" /></span>
<p><strong>Телефон:</strong> {{ this.theme.phone }}</p>
</div>
<div class="contacts-item">
<span class="contacts-icon"><img src="{{ 'assets/new/images/address.png'|theme}}" alt="" /></span>
<p><strong>Адрес:</strong>{{ this.theme.address }}</p>
</div>
</div>
<h2>Свяжитесь с нами</h2>
<p>Есть идея или сообщение для нашего агентства? Заполните форму ниже, и мы обязательно с вами свяжемся. Ваши предложения и вопросы помогают нам становиться лучше!</p>
</div>
<div class="contact-left">
<div class="trending-head contact-head">
<h2>{{ 'contact.feedback'|_ }}</h2>
<span></span>
</div>
<form class="contact-form">
<div class="contact-content">
<div class="contact-block">
<label for="name" name="name">Ваше имя <span>*</span></label>
<input type="text" required placeholder="Аманов Аман" id="name" />
</div>
<div class="contact-block">
<label for="email" name="email">Ваше Email <span>*</span></label>
<input required type="email" placeholder="amanamanov@gmail.com" id="email" />
</div>
<div class="contact-block">
<label for="message" name="message">Тема сообщения</label>
<textarea name="message" id="message" rows="10" placeholder="Тема сообщения"></textarea>
</div>
<div class="contact-antispam">
<img src="{{'assets/new/images/antispam.jpg'|theme}}" alt="" />
</div>
<div class="contact-block">
<label for="code" name="code">Введите текст на картинке<span>*</span></label>
<input type="text" required id="code" />
</div>
<button type="submit">Отправить</button>
</div>
<div class="contact-send"></div>
</form>
</div>
</div>
</div>
</main>
{% put scripts %}
<script src="{{ 'assets/new/scripts/marquee/marquee3k.js'|theme}}"></script>
<script src="{{ 'assets/new/scripts/core/main.js'|theme}}"></script>
{% endput %}

View File

@ -1,25 +0,0 @@
title = "demosearch"
url = "new/demosearch"
layout = "new/master-inside"
is_hidden = 0
robot_index = "noindex"
robot_follow = "follow"
[meilisearch]
==
<!-- HEAD end ======== -->
<main class="rubric-main">
<div class="container">
<div class="rubric-inner">
<div class="trending-head">
<h2>{{'page.search'|_}}</h2>
<span></span>
</div>
{% component 'meilisearch' %}
</div>
</div>
</main>

View File

@ -19,16 +19,9 @@ categoryPage = "new/category"
postPage = "new/newPost"
[mediaView]
[expertForm]
==
<?php
function onStart(){
//dd("1");
// $postId = $this->param('id');
// $currentPost = RainLab\Blog\Models\Post::where('id', $postId)->with(['category_groups'])->first();
$currentLocale = $this->activeLocale;
@ -166,7 +159,16 @@ function onStart(){
<div class="container">
<div class="rubric-inner">
<div class="trending-head">
<h2 style="text-transform: capitalize;">{% if category.name != "" %}{{category.name}}{% else %} {% if group == 'media' %} {{ group }} {% else %}{{ groupName.name }}{% endif %} {% endif %}</h2>
<h2 style="text-transform: capitalize;">
{% if category.name != "" %}
{{category.name}}
{% else %}
{% if group == 'media' %}
{{ group }}
{% else %}
{{ groupName.name }}
{% endif %}
{% endif %}</h2>
<span></span>
</div>

View File

@ -192,6 +192,6 @@ function onStart() {
}
});
</script>
<script src="{{ 'assets/new/scripts/swiper/swiper-bundle.min.js'|theme}}"></script>
<script src="{{'assets/new/scripts/core/article.js'|theme}}"></script>
{% endput %}