10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Civictech1年目Advent Calendar 2020

Day 12

昔懐かしのアクセスカウンターを作った話

Last updated at Posted at 2020-12-12

この記事はCivictech1年目 Advent Calendar 2020 12日目の記事です。

11日目は @t-mat さんのシビックテック1年目の取組と課題でした。
私も今年入ってから初めてシビックテックというものを知ったので、この後t振り返ろうかなと思っています。

TL;DR

「BADオープンデータ供養寺」建立の宮大工をしていた時に作ったアクセスカウンターが同できてるかをゆるゆる書くっていう記事です。

BADオープンデータ供養寺のソースコードは https://github.com/codeforjapan/bad-opendata-temple です!
いまだに面白いissueが残ってたりしますので皆さんもぜひ...!

BADオープンデータ供養寺自体は https://bad-data.rip にありますので興味のある方はぜひ。(.ripなんてドメイン初めて聞いた...)

はじめに

BADオープンデータ供養寺とは

同じく12日目のCivictech テック好きのカレンダーに書いてらっしゃる @kaizumaki さんの BADオープンデータ供養寺、匠たちの技から引用をさせていただきまして...

オープンデータ供養寺とは

住職(※1)の「ぶっ飛んだデザインにした方が良いのでは」というひとことに、腕に覚えありの宮大工(※2)達が結集し、懐かしのインターネッツネタをモダンコーディングで再現しようと力を合わせたのでした。

※1…言わずと知れた我らがリーダー、下山紗代子氏のこと。オープンデータの普及に東へ西へと駆け回っている。すっかり「住職」と呼ばれるのが板についている。
※2…私たちの間ではエンジニアのことを「宮大工」、デザイナーのことを「宮造りデザイナー」としている。そして彼らの名前は「〜〜匠」と呼ばれる。

書いてある通りではあるんですが、

  • カーソルをローソクにする
  • お経を流す
  • お鈴を鳴らす
  • 餅を投げる

だったり、

  • MARQUEEタグじゃないマーキー
  • CGIじゃないアクセスカウンター

など、ローテク?昔懐かし?のようなハイテクノロジー()の数々があります

私はこの CGIじゃないアクセスカウンターを作ったのでこれについてこのあとかこうかと思います(ほかのことについては引用元をぜひ...)

CGIじゃないアクセスカウンターってどゆこと????

タイトルにも書いてる通り、今回のアクセスカウンターにCGIを使っていません!
正真正銘Reactのコンポーネントです。
(このタイトルで読みに来る方は大体CGIが何かわかってると思うのでそこは書きません)

(なぜcgiじゃないのかというとそれをホストするばしょがないからですね)

アクセスカウンターなのでアクセス数を記録しないといけない。
しかもそれは共通させなきゃいけないのでどこかにDBを持つ必要がある。
じゃあどうしてるのか....
実はGoogle Spreadsheet + Google App Scriptでできています。

React側

accessCounter.tsx
import React, {
  ReactElement,
  useEffect,
  useState,
} from 'react';
import styled from 'styled-components';

const AccessCounterContent = styled.div`
  font-size: 30px;
`;

const NumberText = styled.span`
  color: #ebff00;
  background-color: #000000;
  padding: 2px 4px;
  margin: 0 2px;
  box-sizing: border-box;
`;

const AccessCounter: React.FC = (): ReactElement => {
  const [accessStr, setAccessStr] = useState('LOADING');
  useEffect(() => {
    fetch(
      'https://script.google.com/macros/s/えーぴーあいの/exec',
    )
      .then((response) => {
        return response.json();
      })
      .then((json) => {
        setAccessStr(
          String(json.your_access).padStart(4, '0'),
        );
        return json;
      })
      .catch((_) => {
        setAccessStr('ERROR');
      });
  }, []);

  return (
    <AccessCounterContent>
      あなたは
      {[...accessStr].map((str, index) => {
        return (
          <NumberText key={str + String(index)}>
            {str}
          </NumberText>
        );
      })}
      人目の参拝者です
    </AccessCounterContent>
  );
};

export default AccessCounter;

分けて解説をすると..

const AccessCounterContent = styled.div`
  font-size: 30px;
`;

const NumberText = styled.span`
  color: #ebff00;
  background-color: #000000;
  padding: 2px 4px;
  margin: 0 2px;
  box-sizing: border-box;
`;

ここでデザインをかいていて...

const AccessCounter: React.FC = (): ReactElement => {
  const [accessStr, setAccessStr] = useState('LOADING');
  useEffect(() => {
    fetch(
      'https://script.google.com/macros/s/えーぴーあいのid/exec',
    )
      .then((response) => {
        return response.json();
      })
      .then((json) => {
        setAccessStr(
          String(json.your_access).padStart(4, '0'),
        );
        return json;
      })
      .catch((_) => {
        setAccessStr('ERROR');
      });
  }, []);

React FCを使っているので、useStateでStateを作成(初期値にLOADINGと文字列を入れておきます)
useEffectでcomponentDidMountedでこの後作るAPIにアクセスしてアクセス数を読み取ります。
ちなみに

String(json.your_access).padStart(4, '0'),

これは23とかで帰ってきた数字を0023とかにするものです

  return (
    <AccessCounterContent>
      あなたは
      {[...accessStr].map((str, index) => {
        return (
          <NumberText key={str + String(index)}>
            {str}
          </NumberText>
        );
      })}
      人目の参拝者です
    </AccessCounterContent>
  );

これは、表示を
image.png
こうしたかったので、
[...accessStr].map((str, index) => {で一文字ずつに分割してmapで回して、

          <NumberText key={str + String(index)}>
            {str}
          </NumberText>

で一文字ずつ分割したコンポーネントとしています。

これが、Reactコンポーネントの動きです。

App Scriptのスクリプトくん

function doGet(e) {
  var sheet = SpreadsheetApp.getActive().getSheetByName('シート1');
  var accessNumber = Number(sheet.getRange("A1").getValues()) + 1;
  sheet.getRange("A1").setValue(accessNumber);
  var result = {
    "your_access": accessNumber
  }
  var out = ContentService.createTextOutput();

    //Mime TypeをJSONに設定
  out.setMimeType(ContentService.MimeType.JSON);

    //JSONテキストをセットする
  out.setContent(JSON.stringify(result));
  return out;
}

簡単な内容ですのでほぼ解説しませんが....
スプシはつないでいるので

  var sheet = SpreadsheetApp.getActive().getSheetByName('シート1');
  var accessNumber = Number(sheet.getRange("A1").getValues()) + 1;
  sheet.getRange("A1").setValue(accessNumber);

でA1に格納している数値を取得して

  var result = {
    "your_access": accessNumber
  }
  var out = ContentService.createTextOutput();

    //Mime TypeをJSONに設定
  out.setMimeType(ContentService.MimeType.JSON);

    //JSONテキストをセットする
  out.setContent(JSON.stringify(result));
  return out;

でgetへの返り値としてます

あとはこれをウェブアプリケーションとして導入をすればアクセスカウンターのAPIの出来上がりです!

おわりに

結構前からいんたーねっとにいる学生ではあるのでアクセスカウンターのcgiは見たことはあるし、使ったこともあるんですが実際に作ったのは初めてでした...
そしてそれ以上にcgiじゃないアクセスカウンターを作ることになるとは.....

こんな面白いものがいろいろそろったBADオープンデータ供養寺をぜひご覧ください!(https://bad-data.rip)

10
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?