<!--
- https://www.youtube.com/watch?v=sxxUK0l8jKE
- https://play.tailwindcss.com/4cuLPqCv05
-->
<div class="p-20 flex justify-center items-center gap-12">
<img class="avatar-sm" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
<img class="avatar" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
<img class="avatar-lg" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
<img class="avatar-xl" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
</div>
class IconListPresenter extends \App\Presenters\BasePresenter
{
/**
* @var Context
* @inject
*/
public $connection;
public function actionDefault()
{
$icons = scandir(INDEX_DIR . '/../webapp/frontapp/svg');
$list = [];
foreach ($icons as $icon) {
if (!strpos($icon, 'svg')) {
continue;
}
$list[] = $icon;
}
$this->template->occurrences = $this->findOccurrences($list);
$this->template->list = $list;
$scan = array_diff(scandir(INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/'), ['.', '..']);
$urls = [];
foreach ($scan as $iconName) {
if (is_file($file = INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/' . $iconName)) {
$urls[str_replace('.txt', '', $iconName)] = file_get_contents($file);
}
}
$this->template->urls = $urls;
}
public function actionUpdateIcons()
{
$icons = scandir(INDEX_DIR . '/../webapp/frontapp/svg');
$list = [];
foreach ($icons as $icon) {
if (!strpos($icon, 'svg')) {
continue;
}
$list[] = $icon;
}
$scan = array_diff(scandir(INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/'), ['.', '..']);
$urls = [];
foreach ($scan as $iconName) {
if (is_file($file = INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/' . $iconName)) {
$urls[str_replace('.txt', '', $iconName)] = file_get_contents($file);
}
}
foreach ($list as $icon) {
if (isset($urls[$icon])) {
$url = $urls[$icon];
$url = str_replace('48px.svg', '20px.svg', $url);
$fetchIcon = file_get_contents($url);
$fetchIcon = str_replace('><path', ' viewBox="0 0 20 20"><path fill="currentColor" ', $fetchIcon);
file_put_contents(INDEX_DIR.'/../webapp/frontapp/svg/' . $icon, $fetchIcon);
// save what we saved
//file_put_contents(INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/' . $icon . '.txt', $url);
}
}
$this->terminate();
}
private function createListFiles()
{
$allFiles = [];
foreach (Finder::findFiles('*.latte')->from(INDEX_DIR . '/../app/BrandCloudModule/') as $key => $splFile) {
$fileResouce = file_get_contents($key);
$allFiles[$key] = $fileResouce;
}
foreach (Finder::findFiles('*.vue')->from(INDEX_DIR . '/../webapp/frontapp/components/') as $key => $splFile) {
$fileResouce = file_get_contents($key);
$allFiles[$key] = $fileResouce;
}
return $allFiles;
}
private function findOccurrences($icons)
{
$allFiles = $this->createListFiles();
$all = [];
foreach ($allFiles as $filePath => $fileResource) {
foreach ($icons as $icon) {
$icon = str_replace('.svg', '', $icon);
//$nicePath = explode('..', $filePath)[1];
$nicePath = $filePath;
preg_match_all('~<aw-icon.+icon=("|\')' . preg_quote($icon) . '("|\')~', $fileResource, $m1);
preg_match_all('~("|\')' . preg_quote($icon) . '("|\')~', $fileResource, $m2);
if (!isset($all[$icon][$nicePath])) {
$all[$icon][$nicePath] = 0;
}
if (count($m1[0])) {
$all[$icon][$nicePath] += count($m1[0]);
}
if (count($m2[0])) {
$all[$icon][$nicePath] += count($m2[0]);
}
}
}
return $all;
}
public function actionSaveUrlIcon()
{
// RAW POST DATA
$data = json_decode(file_get_contents("php://input"));
// icon fetch & save
$url = str_replace('48px.svg', '20px.svg', $data->url);
$fetchIcon = file_get_contents($url);
$fetchIcon = str_replace('><path', ' viewBox="0 0 20 20"><path fill="currentColor" ', $fetchIcon);
file_put_contents(INDEX_DIR.'/../webapp/frontapp/svg/' . $data->icon, $fetchIcon);
// save what we saved
file_put_contents(INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/'.$data->icon . '.txt', $data->url);
// data
echo json_encode($data);
$this->terminate();
}
}
<?php
/*
https://www.nidup.io/blog/manipulate-google-sheets-in-php-with-api
*/
require './vendor/autoload.php';
// configure the Google Client
$client = new \Google_Client();
$client->setApplicationName('Google Sheets API');
$client->setScopes([\Google_Service_Sheets::SPREADSHEETS]);
$client->setAccessType('offline');
// credentials.json is the key file we downloaded while setting up our Google Sheets API
$path = '***'; //google console admin need to generate this file
$client->setAuthConfig($path);
// configure the Sheets Service
$service = new \Google_Service_Sheets($client);
$spreadsheetId = '***'; // get with share with and see to url
// the spreadsheet id can be found in the url https://docs.google.com/spreadsheets/d/143xVs9lPopFSF4eJQWloDYAndMor/edit
$spreadsheet = $service->spreadsheets->get($spreadsheetId);
var_dump($spreadsheet);
// all values
$range = 'List 1'; // here we use the name of the Sheet to get all the rows
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
var_dump($values);
// rows by range
$range = 'List 1!A1:F10';
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
var_dump($values);
// cells of column
$range = 'List1!B1:B21'; // the column containing the movie title
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
var_dump($values);
// rows into json objects
$range = 'Sheet1';
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$rows = $response->getValues();
// Remove the first one that contains headers
$headers = array_shift($rows);
// Combine the headers with each following row
$array = [];
foreach ($rows as $row) {
$array[] = array_combine($headers, $row);
}
var_dump($array);
/*
$jsonString = json_encode($array, JSON_PRETTY_PRINT);
print($jsonString);
*/
// append new row
$newRow = [
'456740',
'Hellboy',
'https://image.tmdb.org/t/p/w500/bk8LyaMqUtaQ9hUShuvFznQYQKR.jpg',
"Hellboy comes to England, where he must defeat Nimue, Merlin's consort and the Blood Queen. But their battle will bring about the end of the world, a fate he desperately tries to turn away.",
'1554944400',
'Fantasy, Action'
];
$rows = [$newRow]; // you can append several rows at once
$valueRange = new \Google_Service_Sheets_ValueRange();
$valueRange->setValues($rows);
$range = 'List 1'; // the service will detect the last row of this sheet
$options = ['valueInputOption' => 'USER_ENTERED'];
$service->spreadsheets_values->append($spreadsheetId, $range, $valueRange, $options);
// update existing
$updateRow = [
'456740',
'Hellboy Updated Row',
'https://image.tmdb.org/t/p/w500/bk8LyaMqUtaQ9hUShuvFznQYQKR.jpg',
"Hellboy comes to England, where he must defeat Nimue, Merlin's consort and the Blood Queen. But their battle will bring about the end of the world, a fate he desperately tries to turn away.",
'1554944400',
'Fantasy, Action'
];
$rows = [$updateRow];
$valueRange = new \Google_Service_Sheets_ValueRange();
$valueRange->setValues($rows);
$range = 'Sheet1!A2'; // where the replacement will start, here, first column and second line
$options = ['valueInputOption' => 'USER_ENTERED'];
$service->spreadsheets_values->update($spreadsheetId, $range, $valueRange, $options);
// delete some row
$range = 'Sheet1!A23:F24'; // the range to clear, the 23th and 24th lines
$clear = new \Google_Service_Sheets_ClearValuesRequest();
$service->spreadsheets_values->clear($spreadsheetId, $range, $clear);
/** with text formatting */
$range = 'List 1!B4';
$params = [
'ranges' => $range,
'fields' => 'sheets.data.rowData.values',
'includeGridData' => true,
];
$response = $service->spreadsheets->get($spreadsheetId, $params);
$data = $response->getSheets()[0]['data'][0]['rowData'][0]['values'][0];
$formattedValue = $data['formattedValue'];
$hyperlink = $data['hyperlink'];
$userEnteredFormat = $data['userEnteredFormat'];
var_dump($formattedValue);
var_dump($hyperlink);
var_dump($userEnteredFormat);
/* Adjustable grid */
.grid {
--column-count: 3;
display: grid;
grid-template-columns: repeat(var(--column-count), 1fr);
}
/* modifiers */
.grid-3 { --column-count: 3; }
.grid-4 { --column-count: 4; }
.grid-5 { --column-count: 5; }
/* custom */
.grid { --column-count: 1; }
@media (min-width: 600px) {
.grid { --column-count: 3; }
}
@media (min-width: 960px) {
.grid { --column-count: 4; }
}
/*
-----------------------------------------------------
*/
/* grid auto-columns */
.auto-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
}
/*
-----------------------------------------------------
*/
/* Pushing the footer down */
.main-layout {
min-height: 100vh;
display: grid;
grid-template-rows: rows 1fr rows;
}
/*
-----------------------------------------------------
*/
/* The stack */
.the-stack {
display: grid;
grid-template-areas: "stack";
place-items: center;
}
.the-stack > * {
grid-area: stack;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button>CLICK ME</button>
<script>
const channel = new BroadcastChannel('myChannel');
document.getElementsByTagName('button')[0].addEventListener('click', e => {
channel.postMessage('Hello from Tab 1' + new Date().getSeconds);
console.log('CHANNEL 1');
});
channel.onmessage = event => {
console.log('Message received in Tab 2:', event.data);
console.log('CHANNEL 2');
};
</script>
</body>
</html>
<?php
private function deleteDuplicateRecursive(Tables\Navigation $duplicateItem)
{
/*
// OLD
$findDescendants = function(Tables\Navigation $parent, array $stack = [], $level = 1) use (&$findDescendants) {
$children = $this->navigation->getAdjacencyList($parent->domain_id)->getChildren($parent->id);
foreach ($children as $child) {
$stack[$level][] = $child;
$stack = $findDescendants($child, $stack, $level + 1);
}
return $stack;
};
// mazeme deti odspoda nahoru
$descendants = $findDescendants($duplicateItem);
foreach (array_reverse($descendants, true) as $level => $descendantArr) {
foreach ($descendantArr as $descendant) {
$this->deleteDuplicate($descendant);
}
}
*/
// NEW, better, shorter
$children = $this->navigation->getAdjacencyList($duplicateItem->domain_id)->getChildren($duplicateItem->id);
foreach ($children as $child) {
$this->deleteDuplicateRecursive($child);
}
// na zaver i roota
$this->deleteDuplicate($duplicateItem);
}
<!--
https://jsbin.com/heqamezuju/edit?html,css,output
-->
<grid>
<item class="l">
aaa
</item>
<item class="r">
bbb
</item>
</grid>
<style>
grid {
display: grid;
grid-template-columns: 1fr 1fr;
max-width: 500px;
outline: 2px solid gray;
height: 500px;
margin: auto;
}
item {
padding: 10px;
}
.r, .l {
position: relative;
isolation: isolate;
}
.r:after {
background: lightgray;
top: 0;
bottom: 0;
left: 0;
width: 50vw;
position: absolute;
content: "";
z-index: -1;
}
.l:after {
background: lightpink;
top: 0;
bottom: 0;
right: 0;
width: 50vw;
position: absolute;
content: "";
z-index: -1;
}
</style>
<!--
https://lab.rjwebdesign.cz/tailwindcss/advanced/
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="./dist/output.css" rel="stylesheet" />
</head>
<body class="p-5">
<h1 class="mb-4 font-bold text-3xl">1) Peer / Group</h1>
<div class="peer group group/second group/third grid place-items-center bg-slate-600 w-20 h-20 mt-10">
<div class="bg-black w-5 h-5 group-hover:bg-red-500"></div>
<div class="bg-black w-5 h-5 group-hover/second:bg-green-500"></div>
<div class="bg-black w-5 h-5 group-hover/third:bg-orange-500"></div>
</div>
<div class="w-20 h-20 bg-orange-400 mt-10 peer-hover:bg-violet-300"></div>
<hr class="my-5" />
<h1 class="mb-4 font-bold text-3xl">2) Animation / Transition</h1>
<div class="w-20 h-20 bg-teal-700 transition-all hover:bg-red-300 delay-300 duration-150"></div>
<hr class="my-5" />
<h1 class="mb-4 font-bold text-3xl">3) Responsivenes / BP (ranges)</h1>
<div class="w-20 h-20 bg-red-500 md:max-lg:bg-green-500"></div>
<hr class="my-5" />
<h1 class="mb-4 font-bold text-3xl">4) Dynamic variants / props / values</h1>
<div class="w-20 h-20 bg-[theme('colors.blue.300')]"></div>
<hr class="my-5" />
<h1 class="mb-4 font-bold text-3xl">5) TW extend / config</h1>
<div class="w-20 h-20 neon-blue"></div>
<hr class="my-5" />
<h1 class="mb-4 font-bold text-3xl">6) TW extend -> COLORS</h1>
<div class="text-primary">Hello how are you?</div>
</body>
</html>