OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)

This commit is contained in:
wangruiguo
2026-09-03 18:49:20 +08:00
commit d647428529
3501 changed files with 1988906 additions and 0 deletions

View File

@@ -0,0 +1,583 @@
<?php
namespace Leantime\Core\Configuration;
use Leantime\Core\Configuration\Attributes\LaravelConfig;
/**
* Default Configuration Class
*/
class DefaultConfig
{
// General =====================================================================================
/**
* @var string Name of your site, can be changed later
*/
#[LaravelConfig('app.name')]
public string $sitename = 'OneBot';
/**
* @var string Default language
*/
#[LaravelConfig('app.locale')]
public string $language = 'en-US';
/**
* @var string Default logo path, can be changed later
*/
public string $logoPath = '/dist/images/logo.svg';
/**
* @var string Default logo URL use for printing (must be jpg or png format)
*/
public string $printLogoURL = '/dist/images/logo.jpg';
/**
* @var string Base URL, trailing slash not needed
*/
#[LaravelConfig('app.url')]
public string $appUrl = '';
/**
* @var string Base of application withotu trailing slash (used for cookies), e.g, /leantime
*/
public string $appDir = '';
/**
* @var bool Send anonymous data <a href='https://docs.leantime.io/#/using-leantime/company-settings?id=telemetry' target='_blank'>More Info</a>.
* No personally identifiable data will be sent and it will be impossible for us to track individual users.
*/
public bool $allowTelemetry = true;
/**
* @var string Default theme
*/
public string $defaultTheme = 'default';
/**
* @var string Primary Theme color
*/
public string $primarycolor;
/**
* @var string Secondary Theme Color
*/
public string $secondarycolor;
/**
* @var string Default timezone
*/
#[LaravelConfig('app.timezone')]
public string $defaultTimezone = 'America/Los_Angeles';
/**
* @var bool Enable to specifiy menu on a project by project basis
*/
public bool $enableMenuType = false;
/**
* @var bool|int Debug flag
*/
#[LaravelConfig('app.debug')]
public int|bool $debug = 0;
/**
* @var bool When true, a denied #[RequiresPermission] attribute blocks the request
* (403 web / JSON-RPC -32001). When false the central enforcer only LOGS the
* would-be denial (audit mode), so permission coverage can be rolled out and
* observed before being enforced. In-method $this->authorize() calls always
* enforce regardless of this flag.
*/
#[LaravelConfig('permissions.enforce')]
public bool $permissionsEnforce = true;
/**
* @var string editor used for code editing
*/
public string $editor = 'phpstorm';
/**
* @var string Application environment
*/
#[LaravelConfig('app.env')]
public string $env = 'production';
/**
* @var string Log Path
*/
public string $logPath = APP_ROOT.'/storage/logs/error.log';
/**
* @var bool Whether or not to enable the Poor Man's Cron fallback
*/
public bool $poorMansCron = true;
/**
* @var bool Don't show user/pass form on login?
*/
public bool $disableLoginForm = false;
// Database ====================================================================================
/**
* @var string Database host
*/
public string $dbHost = 'localhost';
/**
* @var string Database username
*/
public string $dbUser = '';
/**
* @var string Database password
*/
public string $dbPassword = '';
/**
* @var string Database name
*/
public string $dbDatabase = '';
/**
* @var string Database port
*/
public string $dbPort = '3306';
// Fileupload ==================================================================================
/**
* @var string Local relative path to store uploaded files (if not using S3)
*/
public string $userFilePath = 'userfiles/';
/**
* @var string Local relative path to store backup files, need permission to write
*/
public string $dbBackupPath = 'userfiles/';
// S3 configuration ============================================================================
/**
* @var bool Set to true if you want to use S3 instead of local files
*/
public bool $useS3 = false;
/**
* @var string S3 Key
*/
public string $s3Key = '';
/**
* @var string S3 Secret
*/
public string $s3Secret = '';
/**
* @var string S3 Bucket
*/
public string $s3Bucket = '';
/**
* @var bool false => https://[bucket].[endpoint] ; true => https://[endpoint]/[bucket]
*/
public bool $s3UsePathStyleEndpoint = false;
/**
* @var string S3 Region
*/
public string $s3Region = '';
/**
* @var string S3 Foldername within S3 (can be empty)
*/
public string $s3FolderName = '';
/**
* @var string|null S3 EndPoint S3 Compatible
*
* @see https://sfo2.digitaloceanspaces.com
*/
public ?string $s3EndPoint = null;
// Sessions ====================================================================================
/**
* @var string Salting sessions. Replace with a strong password
*/
#[LaravelConfig('app.key')]
public string $sessionPassword = '3evBlq9zdUEuzKvVJHWWx3QzsQhturBApxwcws2m';
/**
* @var int How many minutes after inactivity should we logout? 480min = 8hours
*/
public int $sessionExpiration = 480;
/**
* @var bool. Sets whether the cookie should only be served via https
*/
#[LaravelConfig('session.secure')]
public bool $sessionSecure = false;
// Email =======================================================================================
/**
* @var string Return email address
*/
public string $email = '';
/**
* @var bool Use SMTP? If set to false, the default php mail() function will be used
*/
public bool $useSMTP = false;
/**
* @var string SMTP host
*/
public string $smtpHosts = '';
/**
* @var bool SMTP use user/password authentication
*/
public bool $smtpAuth = true;
/**
* @var string SMTP username
*/
public string $smtpUsername = '';
/**
* @var string SMTP password
*/
public string $smtpPassword = '';
/**
* @var bool SMTP Enable TLS encryption automatically if a server supports it
*/
public bool $smtpAutoTLS = true;
/**
* @var string SMTP Security protocol (usually one of: TLS, SSL, STARTTLS)
*/
public string $smtpSecure = '';
/**
* @var bool SMTP Allow insecure SSL: Don't verify certificate, accept self-signed, etc.
*/
public bool $smtpSSLNoverify = false;
/**
* @var int SMTP Port (usually one of 25, 465, 587, 2526)
*/
public int $smtpPort = 587;
// ldap default settings (can be changed in company settings) ==================================
/**
* @var bool Set to true if you want to use LDAP
*/
public bool $useLdap = false;
/**
* @var string Select the correct directory type. Currently Supported: OL - OpenLdap, AD - Active Directory
*/
public string $ldapType = 'OL';
/**
* @var string LDAP host (FQDN)
*/
public string $ldapHost = '';
/**
* @var int LDAP port
*/
public int $ldapPort = 389;
/**
* @var string LDAP domain
*/
public string $ldapDomain = '';
/**
* @var string LDAP base DN
*/
public string $ldapUri = '';
/**
* @var string Location of users, example: CN=users,DC=example,DC=com
*/
public string $ldapDn = '';
/**
* @var string Default LDAP keys in your directory. Works for OL
*/
public string $ldapKeys = '{
"username":"uid",
"groups":"memberof",
"email":"mail",
"firstname":"displayname",
"lastname":"",
"phone":"",
"jobTitle":"title",
"jobLevel":"level",
"department":"department"
}';
// For AD use
/*
public $ldapKeys = '{
"username":"cn",
"groups":"memberof",
"email":"mail",
"firstname":"givenname",
"lastname":"sn",
"phone":"telephoneNumber",
"jobTitle":"title",
"jobLevel":"level",
"department":"department"
}';
*/
/**
* @var bool Create users
* Create user if not exists
*/
public bool $ldapCreateUser = false;
/**
* @var string Default role assignments upon first login. (Optional) Can be updated in user settings for each user
*/
public string $ldapLtGroupAssignments = '{
"5": {
"ltRole":"readonly",
"ldapRole":""
},
"10": {
"ltRole":"commenter",
"ldapRole":""
},
"20": {
"ltRole":"editor",
"ldapRole":""
},
"30": {
"ltRole":"manager",
"ldapRole":""
},
"40": {
"ltRole":"admin",
"ldapRole":""
},
"50": {
"ltRole":"owner",
"ldapRole":"administrators"
}
}';
// Default Leantime Role on creation. (set to editor)
/**
* @var int Default Leantime Role on creation. (set to editor)
*/
public int $ldapDefaultRoleKey = 20;
// Plugin Settings ==============================================================================
/**
* @var string Comma separated list of plugins that will always be loaded
*/
public string $plugins = '';
/**
* @var string The Url of the Marketplace
**/
public string $marketplaceUrl = 'https://marketplace.leantime.io/';
// OIDC Settings ================================================================================
/**
* @var bool Set to true if you want to use OIDC
*/
public bool $oidcEnable = false;
/**
* @var string OIDC Provider URL
*/
public string $oidcProviderUrl = '';
/**
* @var string OIDC Client ID
*/
public string $oidcClientId = '';
/**
* @var string OIDC Client Secret
*/
public string $oidcClientSecret = '';
/**
* @var string Custom Auto discover URL
*/
public string $oidcAutoDiscoverUrl = '';
/**
* @var string OIDC Auth URL
*/
public string $oidcAuthUrl = '';
/**
* @var string OIDC Token URL
*/
public string $oidcTokenUrl = '';
/**
* @var string OIDC JWKS URL
*/
public string $oidcJwksUrl = '';
/**
* @var string OIDC User Info URL
*/
public string $oidcUserInfoUrl = '';
/**
* @var string OIDC Certificate String
*/
public string $oidcCertificateString = '';
/**
* @var string OIDC Certificate File
*/
public string $oidcCertificateFile = '';
/**
* @var string OIDC Scopes
*/
public string $oidcScopes = 'openid profile email';
/**
* @var bool create user
*
* Create user if not exists
*/
public bool $oidcCreateUser = false;
/**
* @var int OIDC
*
* Default Role for new users
*/
public int $oidcDefaultRole = 20;
/**
* @var string OIDC Field Email
*/
public string $oidcFieldEmail = 'email';
/**
* @var string OIDC Field First Name
*/
public string $oidcFieldFirstName = 'given_name';
/**
* @var string OIDC Field Last Name
*/
public string $oidcFieldLastName = 'family_name';
/**
* @var string OIDC Field Phone
*/
public string $oidcFieldPhone = '';
/**
* @var string OIDC Field Job Title
*/
public string $oidcFieldJobtitle = '';
/**
* @var string OIDC Field Job Level
*/
public string $oidcFieldJoblevel = '';
/**
* @var string OIDC Field Department
*/
public string $oidcFieldDepartment = '';
// Redis Settings ===============================================================================
/**
* @var bool Set to true if you want to use Redis
*/
public bool $useRedis = false;
/**
* @var bool Set to true if you want to use a redis cluster
*/
public bool $useCluster = false;
/**
* @var string Redis URL
*/
#[LaravelConfig('redis.default.url')]
public string $redisUrl = '';
/**
* @var string Redis Host
*/
#[LaravelConfig('redis.default.host')]
public string $redisHost = '127.0.0.1';
/**
* @var string Redis Port
*/
#[LaravelConfig('redis.default.port')]
public string $redisPort = '6379';
/**
* @var string Redis Password
*/
#[LaravelConfig('redis.default.password')]
public string $redisPassword = '';
/**
* @var string Redis Password
*/
#[LaravelConfig('redis.default.tls')]
public string $redisScheme = 'tls';
// Security/Rate Limiting Settings ===============================================================================
/**
* @var string trusted Proxies
*/
public string $trustedProxies = '127.0.0.1,REMOTE_ADDR';
/**
* @var int rate limit on all requests
*/
public int $ratelimitGeneral = 2000;
/**
* @var int rate limit on API requests (per user+IP per minute). 120 = 2 req/s sustained —
* enough for mobile-app sync bursts and integration polling while still catching
* runaway scripts; in line with comparable tools (GitHub ~83/min, Jira ~100/min).
*/
public int $ratelimitApi = 120;
/**
* @var int rate limit on auth requests
*/
public int $ratelimitAuth = 20;
/**
* @var int rate limit on MCP endpoint requests (per user+IP per minute). Higher than the API
* limit because agentic LLM clients burst many parallel tool calls per turn.
*/
public int $ratelimitMcp = 300;
/**
* @var int rate limit on signup + user-invite POSTs (per IP per minute). These endpoints
* send email and provision resources, so they get a tight budget (invite-spam abuse).
*/
public int $ratelimitSignup = 5;
/**
* @var int maximum user invites per inviting user per hour
*/
public int $ratelimitInvitesUser = 10;
/**
* @var int maximum user invites per installation per day. Raise for legitimate bulk
* onboarding (CSV/directory imports).
*/
public int $ratelimitInvitesTenant = 30;
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Leantime\Views\Composers;
use Leantime\Core\UI\Composer;
use Leantime\Core\UI\Theme;
class Entry extends Composer
{
public static array $views = [
'global::layouts.entry',
];
private Theme $themeCore;
public function init(Theme $themeCore): void
{
$this->themeCore = $themeCore;
}
public function with(): array
{
$this->themeCore->getActive();
$logoUrl = $this->themeCore->getLogoUrl();
return [
'logoPath' => $logoUrl ?: BASE_URL.'/dist/images/logo.svg',
];
}
}

View File

@@ -0,0 +1,328 @@
<?php
namespace Leantime\Core;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Support\Facades\Log;
use Leantime\Core\Configuration\Environment;
use Leantime\Core\Events\DispatchesEvents;
use Leantime\Core\Support\NameSanitizer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;
/**
* Mail class - mails with php mail()
*
* @version 1.0
*
* @license GNU/AGPL-3.0, see license.txt
*/
class Mailer
{
use DispatchesEvents;
public string $cc;
public string $bcc;
public string $text = '';
public string $subject;
public string $context;
private PHPMailer $mailAgent;
/**
* @var string
*/
private mixed $emailDomain;
private Language $language;
private string $logo;
private string $companyColor;
private string $html;
private bool $hideWrapper = false;
public bool $nl2br = true;
/**
* __construct - get configurations
*
* @return void
*/
public function __construct(Environment $config, Language $language)
{
if ($config->email != '') {
$this->emailDomain = $config->email;
} else {
$host = $_SERVER['HTTP_HOST'] ?? 'leantime';
$this->emailDomain = 'no-reply@'.$host;
}
$this->emailDomain = self::dispatch_filter('fromEmail', $this->emailDomain, $this);
// PHPMailer
$this->mailAgent = new PHPMailer(false);
$this->mailAgent->CharSet = 'UTF-8'; // Ensure UTF-8 is used for emails
// Use SMTP or php mail().
if (filter_var($config->useSMTP, FILTER_VALIDATE_BOOLEAN) === true) {
if ($config->debug) {
$this->mailAgent->SMTPDebug = 4; // ensure all aspects (connection, TLS, SMTP, etc) are covered
$this->mailAgent->Debugoutput = function ($str, $level) {
Log::debug($level.' '.$str);
};
} else {
$this->mailAgent->SMTPDebug = 0;
}
$this->mailAgent->Timeout = 20;
$this->mailAgent->isSMTP(); // Set mailer to use SMTP
$this->mailAgent->Host = $config->smtpHosts; // Specify main and backup SMTP servers
if (isset($config->smtpAuth)) {
$this->mailAgent->SMTPAuth = filter_var($config->smtpAuth, FILTER_VALIDATE_BOOLEAN); // Enable SMTP user/password authentication
} else {
$this->mailAgent->SMTPAuth = true;
}
$this->mailAgent->Username = $config->smtpUsername; // SMTP username
$this->mailAgent->Password = $config->smtpPassword; // SMTP password
$this->mailAgent->SMTPAutoTLS = $config->smtpAutoTLS ?? true; // Enable TLS encryption automatically if a server supports it
$this->mailAgent->SMTPSecure = $config->smtpSecure; // Enable TLS encryption, `ssl` also accepted
$this->mailAgent->Port = (int) $config->smtpPort; // TCP port to connect to
if (isset($config->smtpSSLNoverify) && filter_var($config->smtpSSLNoverify, FILTER_VALIDATE_BOOLEAN) === true) { // If enabled, don't verify certifcates: accept self-signed or expired certs.
$this->mailAgent->SMTPOptions = [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
],
];
}
} else {
$this->mailAgent->isMail();
}
$this->logo = ! session()->has('companysettings.logoPath') ? '/dist/images/logo_blue.png' : session('companysettings.logoPath');
$this->companyColor = ! session()->has('companysettings.primarycolor') ? '#006c9e' : session('companysettings.primarycolor');
$this->language = $language;
}
/**
* setContext - sets the context for the mailing
* (used for filters & events)
*/
public function setContext($context): void
{
$this->context = $context;
}
/**
* setText - sets the mailtext
*/
public function setText($text): void
{
$this->text = $text;
}
/**
* setHTML - set Mail html (no function yet)
*/
public function setHtml($html, bool $hideWrapper = false): void
{
$this->hideWrapper = $hideWrapper;
$this->html = $html;
}
/**
* setSubject - set mail subject
*/
public function setSubject($subject): void
{
$this->subject = $subject;
}
/**
* dispatchMailerEvent - dispatches a mailer event
*/
private function dispatchMailerEvent($hookname, $payload, array $additional_params = []): void
{
$this->dispatchMailerHook('event', $hookname, $payload, $additional_params);
}
/**
* dispatchMailerFilter - dispatches a mailer filter
*/
private function dispatchMailerFilter($hookname, $payload, array $additional_params = []): mixed
{
return $this->dispatchMailerHook('filter', $hookname, $payload, $additional_params);
}
/**
* dispatchMailerHook - dispatches a mailer hook
*
* @throws BindingResolutionException
*/
private function dispatchMailerHook($type, $hookname, $payload, array $additional_params = []): mixed
{
if ($type !== 'filter' && $type !== 'event') {
return false;
}
$hooks = [$hookname];
if (! empty($this->context)) {
$hooks[] = "$hookname.{$this->context}";
}
$filteredValue = null;
foreach ($hooks as $hook) {
if ($type == 'filter') {
$filteredValue = self::dispatch_filter($hook, $payload, $additional_params);
} elseif ($type == 'event') {
self::dispatch_event($hook, $payload);
}
}
if ($type == 'filter') {
return $filteredValue;
}
return null;
}
/**
* sendMail - send the mail with mail()
*
* @throws Exception
*/
public function sendMail(array $to, $from): void
{
$this->dispatchMailerEvent('beforeSendMail', []);
$to = $this->dispatchMailerFilter('sendMailTo', $to, []);
$from = $this->dispatchMailerFilter('sendMailFrom', $from, []);
$this->mailAgent->isHTML(true); // Set email format to HTML
// The From display name must never carry user-controlled content (invite-spam abuse
// used attacker firstnames here). Callers pass fixed labels; sanitize regardless.
$fromName = NameSanitizer::clean($from);
$fromDisplay = ($fromName === '' || strcasecmp($fromName, 'Leantime') === 0)
? 'Leantime'
: $fromName.' (Leantime)';
$this->mailAgent->setFrom($this->emailDomain, $fromDisplay);
$this->mailAgent->Subject = $this->subject;
if (str_contains($this->logo, 'images/logo.svg')) {
$this->logo = '/dist/images/logo_blue.png';
}
$logoParts = parse_url($this->logo);
if (isset($logoParts['scheme'])) {
// Logo is URL
$inlineLogoContent = $this->logo;
} else {
if (file_exists(ROOT.''.$this->logo) && $this->logo != '' && is_file(ROOT.''.$this->logo)) {
// Logo comes from local file system
$this->mailAgent->addEmbeddedImage(ROOT.''.$this->logo, 'companylogo');
} else {
$this->mailAgent->addEmbeddedImage(ROOT.'/dist/images/logo_blue.png', 'companylogo');
}
$inlineLogoContent = 'cid:companylogo';
}
$mailBody = $this->hideWrapper ? $this->html : app('blade.compiler')::render(
$this->dispatchMailerFilter('bodyTemplate', '<table width="100%" style="background:#fefefe; padding:15px; ">
<tr>
<td align="center" valign="top">
<table width="600" style="width:600px; background-color:#ffffff; border:1px solid #ccc; border-radius:5px;">
<tr>
<td style="padding:20px 10px; text-align:center;">
<img alt="Logo" src="{!! $inlineLogoContent !!}" width="150" style="width:150px;">
</td>
</tr>
<tr>
<td style=\'padding:10px; font-family:"Lato","Helvetica Neue",helvetica,sans-serif; color:#666; font-size:16px; line-height:1.7;\'>
{!! $headline !!}
<br/>
{!! $content !!}
<br/><br/>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="center" style=\'padding:10px; font-family:"Lato","Helvetica Neue",helvetica,sans-serif; color:#666; font-size:14px; line-height:1.7;\'>
{!! $unsub_link !!}
</td>
</tr>
</table>'),
$this->dispatchMailerFilter(
'mailBodyParams',
[
'inlineLogoContent' => $inlineLogoContent,
'headline' => $this->language->__('email_notifications.hi'),
'content' => $this->nl2br ? nl2br($this->html) : $this->html,
'unsub_link' => sprintf($this->language->__('email_notifications.unsubscribe'), BASE_URL.'/users/editOwn/'),
]
)
);
$mailBody = $this->dispatchMailerFilter(
'bodyContent',
$mailBody,
[
[
'companyColor' => $this->companyColor,
'logoUrl' => $inlineLogoContent,
'languageHiText' => $this->language->__('email_notifications.hi'),
'emailContentsHtml' => nl2br($this->html),
'unsubLink' => sprintf($this->language->__('email_notifications.unsubscribe'), BASE_URL.'/users/editOwn/'),
],
]
);
$this->mailAgent->Body = $mailBody;
$altBody = $this->dispatchMailerFilter(
'altBody',
$this->text,
[]
);
$this->mailAgent->AltBody = $altBody;
if (is_array($to)) {
$to = array_unique($to);
foreach ($to as $recip) {
try {
$this->mailAgent->addAddress($recip);
$this->mailAgent->send();
} catch (Exception $e) {
Log::error($this->mailAgent->ErrorInfo);
Log::error($e);
}
$this->mailAgent->clearAllRecipients();
}
}
$this->dispatchMailerEvent('afterSendMail', $to);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html dir="{{ __('language.direction') }}" lang="{{ __('language.code') }}">
<head>
@include('global::sections.header')
@stack('styles')
</head>
<body class="" hx-ext="preload" hx-headers='{"X-CSRF-TOKEN": "{{ csrf_token() }}"}'>
@include('global::sections.appAnnouncement')
<div class="mainwrapper menu{{ session("menuState") ?? "closed" }}">
<div class="header">
<div class="headerinner">
<a class="btnmenu" href="javascript:void(0);"></a>
<a class="barmenu" href="javascript:void(0);">
<span class="fa fa-bars"></span>
</a>
<div class="logo">
<a
href="{{ BASE_URL }}"
style="background-image: url('{{ BASE_URL }}/dist/images/logo.svg')"
>&nbsp;</a>
</div>
@include('menu::headMenu')
</div><!-- headerinner -->
</div><!-- header -->
<div class="overlay" style="position: relative">
<div class="leftpanel">
<div class="leftmenu">
@include('menu::menu')
</div><!-- leftmenu -->
</div>
<div class="rightpanel {{ $section }}">
<div class="primaryContent">
@isset($action, $module)
@include("$module::$action")
@else
@yield('content')
@endisset
<div class="clearfix"></div>
@include('global::sections.footer')
</div>
</div>
</div><!-- rightpanel -->
<div class="menu-backdrop" aria-hidden="true"></div>
</div><!-- mainwrapper -->
@include('global::sections.pageBottom')
@stack('scripts')
@include('help::helpermodal')
</body>
</html>

View File

@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html dir="{{ __('language.direction') }}" lang="{{ __('language.code') }}">
<head>
@include('global::sections.header')
<style>
.leantimeLogo { position: fixed; bottom: 10px; right: 10px; }
</style>
@stack('styles')
</head>
<body class="loginpage" style="height:100%;" hx-headers='{"X-CSRF-TOKEN": "{{ csrf_token() }}"}'>
<div class="header hidden-gt-sm tw-p-[10px]" style="background:var(--header-gradient)">
<a href="{!! BASE_URL !!}" target="_blank">
<img src="{{ BASE_URL }}/dist/images/logo.svg" class="tw-h-full "/>
</a>
</div>
<div class="row" style="min-height:100vh; max-width: 98vw; height: auto;">
<div class="col-md-4 hidden-phone regLeft">
<div class="logo">
<a href="{!! BASE_URL !!}" target="_blank">
<img src="{{ BASE_URL }}/dist/images/logo.svg" />
</a>
</div>
<div class="welcomeContent">
@dispatchFilter('welcomeText', '<h1 class="mainWelcome">'.$language->__("headlines.welcome_back").'</h1>')
</div>
@dispatchFilter('belowWelcomeText', '')
</div>
<div class="col-md-8 col-sm-12 regRight">
<div class="regpanel">
<div class="regpanelinner">
@if($logoPath != '')
<a href="{!! BASE_URL !!}" target="_blank">
@if(!str_ends_with($logoPath, "dist/images/logo.svg" ))
<img src="{{ $logoPath }}" class="tw-h-full "/>
@endif
</a>
@endif
@isset($action, $module)
@include("$module::$action")
@else
@yield('content')
@endisset
</div>
</div>
</div>
<div class="leantimeLogo">
<img style="height: 25px;" src="{!! BASE_URL !!}/dist/images/logo-powered-by-leantime.png">
</div>
</div>
@include('global::sections.pageBottom')
@stack('scripts')
</body>
</html>

View File

@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html dir="{{ __('language.direction') }}" lang="{{ __('language.code') }}">
<head>
@include('global::sections.header')
<style>
.leantimeLogo { position: fixed; bottom: 10px; right: 10px; }
</style>
@stack('styles')
</head>
<body class="loginpage" style="height:100%;" hx-headers='{"X-CSRF-TOKEN": "{{ csrf_token() }}"}'>
<div class="header hidden-gt-sm tw-p-[10px]" style="background:var(--header-gradient)">
<a href="{!! BASE_URL !!}" target="_blank">
<img src="{{ BASE_URL }}/dist/images/logo.svg" class="tw-h-full "/>
</a>
</div>
<div class="row " style="height:100%; width: 99%;">
<div class="col-md-4 hidden-phone regLeft">
<div class="logo">
<a href="{!! BASE_URL !!}" target="_blank"><img src="{{ BASE_URL }}/dist/images/logo.svg" /></a>
</div>
<div class="welcomeContent">
<h1 class="mainWelcome">
Oops, something is off.
</h1>
</div>
</div>
<div class="col-md-8 col-sm-12 regRight">
<div class="regpanel">
<div class="regpanelinner">
@isset($action, $module)
@include("$module::$action")
@else
@yield('content')
@endisset
</div>
</div>
</div>
<div class="leantimeLogo">
<img style="height: 25px;" src="{!! BASE_URL !!}/dist/images/logo-powered-by-leantime.png">
</div>
</div>
@include('global::sections.pageBottom')
@stack('scripts')
</body>
</html>