[구글 태그매니저] 구글 태그매니저 아이디클릭 하위요소 클릭 문제

기타|2022. 6. 1. 22:54
반응형

click id로 트리거를 세팅했는데 

트리거 가 되지 않았다.

 

원인은  id를 가진 버튼이 부모인데 

버튼안의 있는 글자가 클릭이 되서 최종적으로 클릭한건 text기 때문에 트리거가 발생 하지 않았다.

 

이 문제의 해결책은

equals 를 선택하느게 아니라 

 

click id 대신 click element를 선택

css 셀렉터로 선택한 뒤 

#myUniqueID, #myUniqueID * 로 해놓으면 아이디를 가진 요소와 모든 하위 요소들이 적용이 된다.

 

댓글()

웹프레임웍 추천 (vue.js, reactjs, futterweb, sveltejs)

Computer 관심/Svelte|2022. 5. 11. 00:25
반응형

주관적인 추천이다. 하지만 Jquery라이브러리를 시작으로 여러가지 프레임워크를 통해 작은 프로젝트를 해본 결과를 바탕으로 추천해 본다. 

 

추천하고 싶은 프레임웍은 바로: 스벨트이다. 

 

영번째 재미있다.

 

첫번째 이유는 매우 쉽다.
다른 프레임웍에 비해 러닝커브가 완만하다. 자바스크립트만 어느정도 알면 바로 시작할 수 있을 정도로 쉽게 배울 수 있다. 예전에 웹을 점령했던 JQuery도 이러한 장점이 있었다. 예전에 웹을 배우는 방식은 자바스크립트로 아주 조금 맛배기를 보곤 바로 jquery로 넘어갔던 기억이 있다. 왜냐면 jquery가 자바스크립트 자체를 배우는것 보다 쉽고 실전에서 써먹기 좋았기 때문이다.

스벨트도 jquery와 같이 쉽게 배울 수 있다는 점에서 추후 사용자들을 흡수 할 것으로 예상 할 수 있다.

 

 

두번째 이유는 빠르다.

스벨트를 설치해보면 알겠지만 설치도 쉽다. 그 설치 자체도 빠르다. 새로운 프로젝트를 계속해서 만들어 내는 사람들에게 특히나 좋아 할 수 있다. 설치만 빠르면 좋은게 아니다. 실행도 빠르고, 동작도 빠르게 빠르게 움직인다.

 

얼마나 가볍고 빠르게 동작하는지를 보고 싶다면 스벨트 프로젝트들을 모아둔 이 사이트에 들어가서 구경해보길 바란다. 게임에서 부터 쇼핑몰, threejs를 적용한 svelte 패키지까지 구경할 수 있다.  

https://madewithsvelte.com/

 

A collection of web projects made with Svelte – Websites, Components, Frameworks, Apps and more!

A collection of web projects made with Svelte – Websites, Components, Frameworks, Apps and more!

madewithsvelte.com

 

이렇게 빠르게 동작할 수 있는 이유는 svelte는 vuejs와 reactjs처럼 virtual DOM을 사용 하는게 아니라. 스벨트가 컴파일러 역활을 하여 작성한 코드를 순수한 자바스크립트로 컴파일 해주기 때문이다. 

 

 

세번째 이유는 가볍다

위에서 말했듯 순수한 자바스크립트로 컴파일을 해준다는 말은 필요없는 패키지들을 불러오지 않고 딱 필요한 코드만 생성해내는 것이다. 그렇기 때문에 빌드된 파일의 크기는 매우 작다. 이는 실행이 빠르게 되도록 만들어준다.

 

 

네번째 이유는 간결하다.

리액트를 사용하면 간단한 프로젝트도 많은 보일러플레이트 코드가 필요하다. 플러터에 관심이 있어서 사용해 플러터웹을 사용해서 작은 관리자 앱을 만들었는데 플러터웹을 이용해서 만든걸 후회 하고 있다. (물론 플러터는 모바일에서는 좋다.) 둘다 보일러플레이트 코드량이 많다. 그런데 스벨트코드를 보면 너무나도 심플하다. 스토어도 기본적으로 제공해주는데 심플하게 사용할 수 있다. 예전에 리덕트를 배우려고 머리 아픈것에 비하면 심플해서 머리 아플게 없다. 

 

 

다섯번째 제공 repl

간단하게 코드를 작성할 수 있는 repl을 제공하는데 깃 계정을 통해서 심플하게 만든 앱을 저장 할 수 있다. 잘 사용하면 생각보다 쓸만하다.

https://svelte.dev/repl

 

Hello world • REPL • Svelte

 

svelte.dev

나는 이 repl를 통해 업무에 필요한 단순한 유틸 파일을 만들어 사용하거나, 심심할때 간단한 디자인이나 아이디어를 구현해보기도 한다. 그런데 아쉽게도 repl에서는 타입스크립트는 지원이 안된다.

 

Ex) repl을 사용하여 그냥 재미로 만들어본 네이버 주식 그래프 검색기

 

 

아래는 비교 해본 다트패드이다. 뭐 하나 실행하는데도 오래 걸린다. 저장기능도 없다. 플러터로 만들어 볼만한 간단한 아이디어를 구현해 보려 했는데 다트패드로는.....ㅠㅠ

https://dartpad.dev/

 

DartPad

 

dartpad.dev

 

 

마지막 결론

어째튼 스벨트는 정말로 좋다. 특히나 개인 프로젝트로 아이디어를 구현하는 것에 스벨트를 사용하면 빠르게 프로토타이핑을 할 수 있다. 기업 내부에서 사용하는 시스템을 만든다고하면 또 추천해 보고 싶은데. 빨리빨리 필요한 기능들을 만들어내기 좋기 때문이다.

 

기업 입장에서도 프로그래밍 어느정도 할 수 있는 사람(나 같은)을 구해서 결과물을 만들어내기 쉽다. 다큐먼트와 튜토리얼도 잘 되어있어서 금방 배울 수 있다. (영어지만... 어렵진 않다.)

 

vuejs를 사용자라면 스벨트를 사용하면 뷰에서 조금 아쉬웠던 간결함을 스벨트에서 찾을 수 있을 것이라 생각한다. (물론 스벨트에서는 커뮤니티의 크기가 아쉽지만..ㅠ)

 

플러터웹으로 웹사이트를 만드는 건.. '왜 힘든길로 ㅠㅠㅠ' 라고 생각된다. - 플러터가 유명하긴하지만 플러터웹은 자료가 정말 없다.

 

리액트는 좋다 커뮤니티도 크고 자료도 많다. 리액트네이티브를 통해 앱을 만드는 자료도 많다. 그런데... 왜 그리 공부할게 많은지..ㅠ '익숙해지면 좋은거 아닌가????' 생각이 든다.  

 

댓글()

스벨트킷 sveltekit에서 tailwindcss와 daisyUi 사용하기

카테고리 없음|2022. 5. 10. 22:59
반응형

HTML 스타일을 할 때 tailwindcss를 사용하면 직접 css를 작성하는 것 보다 쉽고 자유롭게 스타일을 할 수 있다. 

https://tailwindcss.com/

 

그리고 이미 테일윈드를 통해 스타일이 만들어져 있는 daisyUi를 사용하게 된다면 예전에 부트스트랩을 사용하 듯. 쉽게 디자인을 만들어 낼 수 있다.

https://daisyui.com/

 

 

 

1. tailwindcss 설치

이 글에서는 스벨트킷에 적용하는 방법을 설명 하려고 한다.

 

스벨트킷을 스켈레톤으로 설치하고 실행하게 되면 아래의 화면을 볼 수 있을 것이다. 

스벨트킷에 tailwindcss를 설치하는 방법은 사실 아래의 주소에 아주 잘 나와있다.

https://tailwindcss.com/docs/guides/sveltekit

 

홈페이지를 따라 해보자

 

스벨트킷 기본파일들

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init tailwind.config.cjs -p
mv postcss.config.js postcss.config.cjs

 

npx tailwindcss init tailwind.config.cjs -p를 cmd에 입력을 하니 

tailwind.config.cjs파일과 postcss.config.js파일이생겼다

 

윈도우에 설치하는 것이기 때문에 

cmd에 mv postcss.config.js postcss.config.cjs 대신 move postcss.config.js postcss.config.cjs 를 치니 

postcss.config.js에서 postcss.config.cjs파일로 바뀌었다. (만일 실수로 postcss.config.js가 남아있게 되면 에러가 발생함)

 

tailwind.config.cjs에 아래와 같이 입력함

module.exports = {
  content: ['./src/**/*.{html,js,svelte,ts}'],
  theme: {
    extend: {}
  },
  plugins: []
};

 

./src/app.css 를 만든 뒤 아래를 입력함

@tailwind base;
@tailwind components;
@tailwind utilities;

./src/routes/__layout.svelte 를 만든뒤

<script>
  import "../app.css";
</script>

<slot />

 

이제 실행해보면 모든 기본 스타일이 없어지게 된다. 

이제 아래 처럼 테일윈드의 클래스를 입력해보자. 스타일이 적용이 되는 것을 볼 수 있다.

 

 

이렇게 tailwind를 설치를 완료했으면 다음으로 daiyUI를 설치해보자.

https://daisyui.com/docs/install/

 

공식문서를 그냥 따라하면 된다.

npm i daisyui

 

tailwind.config.js에 아래와 같이 추가함

module.exports = {
  //...
  plugins: [require("daisyui")],
}

 

이렇게 daisyUI를 설치하게 되었다. 

index.svelte에 daiyUI의 예제를 입력해 보앗다.

<div class="alert alert-info shadow-lg">
  <div>
    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current flex-shrink-0 w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
    <span>New software update available.</span>
  </div>
</div>

 

결과:

 

댓글()

sveltekit firebase 로그인/로그아웃 만들기

Computer 관심/Svelte|2022. 5. 8. 22:37
반응형

firebase 9 버전이다.

 

app.js를 만들기.

import { initializeApp } from "firebase/app";
import { getAuth, GoogleAuthProvider } from "firebase/auth";

const firebaseConfig = {
  apiKey: "xxxxxxxxx-gG2DEYRrdnOx-Jtw7PRoso",
  authDomain: "xxxx.firebaseapp.com",
  projectId: "xxxxx",
  storageBucket: "xxxx.appspot.com",
  messagingSenderId: "xxxx",
  appId: "xxxxxxx",
  measurementId: "xxxxx"
};

//named export를 사용해서 필요한 것들을 내보냄
// Initialize Firebase

export const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const provider = new GoogleAuthProvider();

 

stores.js 만들기

import { writable } from "svelte/store";

export const user = writable({})
export const isLoggedIn = writable(false)

 

 

 

index.svelte

<script>
  import {auth, provider} from '../lib/app.js'
  import {signInWithPopup, onAuthStateChanged, signOut} from "firebase/auth";
  import {user, isLoggedIn} from '../stores'
  
  let isLoading = true

  async function loginInGoogle(){
    await signInWithPopup(auth, provider).then((result)=>{
      console.log(result.user)
      $user = result.user
      $isLoggedIn = true
    }).catch((error) => {

    })

  }
  async function logOut(){
    signOut(auth)
  }
 

  onAuthStateChanged(auth,(currUser) => {
    isLoading = false
    if (currUser) {
      // User is signed in, see docs for a list of available properties
      // https://firebase.google.com/docs/reference/js/firebase.User
      $user = currUser
      $isLoggedIn = true

      
    } else {
      $isLoggedIn = false
      $user = currUser
      // ...
    }
  });

</script>


{#if !isLoading}
  {#if $isLoggedIn}
    {$user.displayName} <button on:click={logOut}>log out</button>
  {:else}
    <button on:click={loginInGoogle}>login</button>
  {/if}
{/if}

 

 

 

 

댓글()

VBA로 차트 오른쪽에 레이블명 자동으로 생성하기(색상, 레이블위치설정)

Computer 관심/Excel & VBA|2022. 3. 9. 15:53
반응형

차트의 레이블을 일일이 마우스 클릭하여 입력하고, 색상까지 바꿔주는게 귀찮아서 자동으로 완성해줄 수 있는 VBA가 있는지 찾아봤다.

그리고 그 코드를 약간 수정해서 아래의 결과물을 보여질 수 있는 코드를 만들었다.

 

 

결과

 

사용방법

차트를 클릭한 뒤 메크로로 아래의 코드를 넣은 모듈을 실행시키면 된다.

 

Sub LastPointLabel()
  Dim mySrs As Series
  Dim iPts As Long
  Dim vYVals As Variant
  Dim vXVals As Variant

  If ActiveChart Is Nothing Then
    MsgBox "Select a chart and try again.", vbExclamation
  Else
    Application.ScreenUpdating = False
    For Each mySrs In ActiveChart.SeriesCollection
      With mySrs
        vYVals = .Values
        vXVals = .XValues
        ' clear existing labels
        .HasDataLabels = False
        
        For iPts = .Points.Count To 1 Step -1
          If Not IsEmpty(vYVals(iPts)) And Not IsError(vYVals(iPts)) _
              And Not IsEmpty(vXVals(iPts)) And Not IsError(vXVals(iPts)) Then
            ' add label
            Set pt = mySrs.Points(iPts)
            pt.ApplyDataLabels _
                ShowSeriesName:=True, _
                ShowCategoryName:=False, ShowValue:=False, _
                AutoText:=True, LegendKey:=False
            Set dl = pt.DataLabel
            With dl
                'text color match to the it's line of the chart
                .Font.Color = mySrs.Format.Line.ForeColor
                .Top = pt.Top - 10
                .Left = pt.Left + 20
                .Font.Size = 12
                .Font.Bold = True
            End With
          End If
        Exit For
        Next
        ' Change the font size to 12
        
      End With
    Next
    ' legend is now unnecessary
    ActiveChart.HasLegend = False
    Application.ScreenUpdating = True
  End If
End Sub

 

참조

https://peltiertech.com/label-last-point-for-excel-2007/

https://stackoverflow.com/questions/59274616/custom-chart-point-datalabel-position

댓글()

[SVELTEKIT] capacitor 사용하여 안드로이드 앱 만들기

Computer 관심/Svelte|2022. 2. 20. 00:40
반응형

아이오닉사용해서 sveltekit 안드로이드 앱만들기

 

이미 스벨트로 만들어 놓은 코드가 있어서, 굳이 플러터 flutter를 사용하지 않고 기존 코드를 이용하여 앱을 만들어 보고 싶었다. 처음 앱으로 빌드할 때 좀 느렸지만 이후엔 빠르게 빌드가 됬다. 

오래 사용해보지 않아 얼마나 좋은지 나쁜지는 잘 모르겠지만 가벼운앱을 만들땐 괜찮을 않을까 싶다.

 

 

1. 기존에 있던 프로젝트에 capacitor 설치하기

npm install @capacitor/core @capacitor/cli

 

2. capacitor init 하기

capacitor를 init할때 스벨트킷의 빌드할 폴더는 build이기 때문에 기본값 www대신 build로 적어 준다..

(혹시라도 init 때 www로 설정해놓더라도 capacitor.config.ts의 webDir에서 나중에 바꿀 수 있으니 걱정할 필요 없다.)

npx cap init

 

3. 안드로이드나 IOS 플랫폼 설치

npm i @capacitor/ios @capacitor/android
npx cap add android //안드로이드 추가
npx cap add ios //ios 추가

 

4. 싱글페이지 빌드용 어뎁터 설치하기

npm i -D @sveltejs/adapter-static

https://github.com/sveltejs/kit/tree/master/packages/adapter-static

 

5.  싱글페이지로 빌드하기 위해 svelte.config에 아래와 같은 코드를 넣어준다. 

import adapter from '@sveltejs/adapter-static';

 

아래 코드를 보듯 기존 import adapter from '@sveltejs/adapter-auto'; 를 대체하였다.

// import adapter from '@sveltejs/adapter-auto';
import adapter from '@sveltejs/adapter-static';
import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	// Consult https://github.com/sveltejs/svelte-preprocess
	// for more information about preprocessors
	preprocess: preprocess(),

	kit: {
		adapter: adapter(
        {fallback: 'index.html'}
        )
	}
};

export default config;

6. routes/+layout.js 파일 만들고 

export const prerender = true

 

 

 

7. 스벨트 빌드하기

npm run build

 

 

 

8.실행시키기

//안드로이드 스튜디오에서 실행
npx cap open android 

//실기기 실행
npx cap run android

 

 

 

 

-----------------------------------------------------

 

 

라이브 리로드

1. capacitor.config.ts의 내용을 아래로 대체함

import { CapacitorConfig } from '@capacitor/cli';

const appId = '앱.아이.디';
const appName = '앱이름';
const server = process.argv.includes('-hmr') ? {
  'url': 'http://192.168.5.67:5173',   // always have http:// in url
  'cleartext': true
} : {};
console.log(server);
const webDir = 'build';

const config: CapacitorConfig = {
  appId,
  appName,
  webDir,
  server
};

if (process.argv.includes('-hmr')) console.log('WARNING: running capacitor with livereload config', config);

export default config;

 

2. svelte를 디버깅 모드로 실행

npm run dev -- --host //호스트를 넣어서 아이피를 오픈해줘야함

 

3. 실기기에서 실행

cmd창을 하나 더 열고 아래의 명령어를 입력함

npx cap run android

 

 

 

 

참조

https://capacitorjs.com/docs/cli

 

Capacitor: Cross-platform native runtime for web apps

Build iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript

capacitorjs.com

 

 

댓글()

스벨트 로그인 비동기 문제

Computer 관심/Svelte|2022. 2. 10. 13:37
반응형

https://www.reddit.com/r/sveltejs/comments/rllo3y/svelte_and_firebase_auth_question/

댓글()

플라스크 팩토리 패턴으로 바꾸기

Computer 관심/Flask|2022. 1. 13. 00:12
반응형

플라스크는 하나에 파이썬 파일에 서버를 쉽게 만들 수 있다. 

엄청 간단한 기능을 만들거나 테스트앱을 만들때 간단히 하나의 파일로 만들면 빠르게 개발 할 수 있다. 

하지만 조금만 앱의 크기가 커지면 하나의 파일로 코드를 작성하는게 불편해 지는 때가 온다.

 

팩토리 패턴을 사용하여 파일을 나눌 수 있다.

 

일단 참고한 사이트는 아래의 사이트이다. 사이트에 어떻게 나누어야 하는지 아주 자세하게 잘 나와있다. 

https://wikidocs.net/81044

 

2-01 플라스크 기초 다지기

현재 파이보 프로젝트는 `projects/myproject` 디렉터리 아래에 pybo.py 파일만 생성한 상태다. 그런데 이보다 규모를 갖춘 플라스크 프로젝트를 만들고자 한 ...

wikidocs.net

 

간략하게 설명한다면

1. 파이썬 메인 파일을 __init__.py로 바꾸어 폴더 통체로 모듈화를 한다

2. views 폴더를 만들어서 url을 적고

3. models.py를 만들어서 모델을 넣는다. 

 

이걸 하는 동안 작은 문제가 발생했는데 다음과 같다.

시작과 함게 디비를 만드는 db.create_all()이 에러를 발생했고 

 

 

__init__.py파일 안에 아래와 같이 코드를 만들었더니 디비가 생성되지 않는 에러가 나타났다. 그런데 

def create_app():


    with app.app_context():
            db.create_all()
            
    from .views import main_views
    app.register_blueprint(main_views.bp)
    return app

 

아래 처럼

with app.app_context():

      db.create_all()

을 맨 마지막에 적으니 작동이 된다. 

 

def create_app():
	
    
    from .views import main_views
    app.register_blueprint(main_views.bp)
    
    with app.app_context():
    	db.create_all()  
    return app

 

 

코드 나눈건 아래 같은 방식으로 나누었다.

 

__init__.py

from flask import Flask
from flask_cors import CORS
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy

# *** 중요 (팩토리 패턴세팅) ***
db = SQLAlchemy()
migrate = Migrate()

# ***** 팩토리 패턴에서 자동으로 실행되는 create_app() 함수 
def create_app():
    app = Flask(__name__)
    CORS(app)

    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///inventory.db" # sqllite
    # app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://로컬유저네임:로컬비번@localhost/default'
    # app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://닉네임:비밀번호@파이썬애니웨어닉네임.mysql.pythonanywhere-services.com/디비네임$default'
    app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {'pool_recycle': 280}
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

    UPLOAD_FOLDER = './downloads'
    
    # *** 중요 (팩토리 패턴세팅) ***
    app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
    db.init_app(app)
    migrate.init_app(app, db)

    from .views import main_views
    app.register_blueprint(main_views.bp)
	
    with app.app_context():
        db.create_all()

    
    return app

 

 

views.py

# *** 중요 (팩토리 패턴세팅): Blueprint 임포트하기 ***
from flask import Blueprint
from flask import request
import pandas as pd
from myapp import db
from myapp.models import ProductInfo, Quots, SalesDetail, StockLevel, Sales, Purchase, Bom, QuotsDetail, PurchaseDetail
import json
from werkzeug.utils import secure_filename
from flask import make_response

# *** 중요 (팩토리 패턴세팅): url 경로 / 기준으로 엔드포인트 만듬 ***
bp = Blueprint('main', __name__, url_prefix='/')

@bp.route("/add_product_info", methods=['GET', 'POST'])
def add_product_info():
    if request.method == 'POST':
        objects = []
     	...
        return '0'
    else:
        return '0'


@bp.route("/csv_upload", methods=['POST'])
def csv_upload():
    if request.method == 'POST':
        counts = {'total':0, 'insert': 0, 'update':0}
        if 'file' not in request.files:
            print('No file part')
            
        file = request.files['file']
        if file.filename == '':
            print('No selected file')

        if file and allowed_file(file.filename):
        ...
        
    print('success')        
    return {'stauts':'success', 'counts':counts}


@bp.route("/product_edit", methods=['POST'])
def product_edit():
    if request.method == 'POST':
        row = json.loads(request.data)['data']
         ...
        db.session.commit()
    return {'res':0}

 

 

models.py

# *** 중요 (팩토리 패턴세팅)__init__에 만든 db 가져오기 ***
from myapp import db
import datetime

class ProductInfo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    article = db.Column(db.String(32), unique=True, nullable=False)
    ...
    #server deafult는 string
    online_shop = db.Column(db.Boolean, nullable=False, server_default='0', default=0)
    stocks = db.relationship("StockLevel")

    def as_dict(self):
        return {c.name: getattr(self, c.name) for c in self.__table__.columns}


class Sales(db.Model):
    __tablename__ = 'sales'
    id = db.Column(db.Integer, primary_key=True)
    ...
    status = db.Column(db.String(16))
    children = db.relationship("SalesDetail")

 

> set FLASK_ENV=development
> flask run

 

댓글()