Your Name 3 jaren geleden
bovenliggende
commit
c69f84770c

+ 7 - 3
hhh/auto_clicks.py

@@ -35,7 +35,10 @@ def get_designer_statistics(designer_list):
 
 #    for q in qlist:
     for q in designer_list:
+#        q+=' 幸福空間'
+#        q+=' hhh'
 
+#        googleurl='https://www.google.com/search?q='+q
         googleurl='https://www.google.com/search?q='+q
 
         jb.get(googleurl)
@@ -54,7 +57,7 @@ def get_designer_statistics(designer_list):
                 if 'hhh.com.tw' in href:
                     webdriver.ActionChains(driver).move_to_element(elmt).perform()
                     webdriver.ActionChains(driver).move_to_element(elmt).click().perform()
-                    time.sleep(5)
+                    time.sleep(15)
                     driver.quit()
                     return
 
@@ -68,6 +71,7 @@ def get_designer_statistics(designer_list):
         time.sleep(3)
 #    print(masters)
 #    print(details)
+    driver.quit()
     return {'masters':masters,'details':details}
 
 def find_master_by_designer(masters,designer):
@@ -94,8 +98,8 @@ def find_master_by_designer(masters,designer):
 
 #設計
 #qlist=['三宅一秀','萬寶隆空間設計','含仰空間設計','元均制作','承炫裝修']
-
-qlist=['春雨時尚空間','萬寶隆空間設計','含仰空間設計','綵韻室內設計','雅典設計','境庭國際設計','張馨室內設計','尚藝室內裝修','豐聚室內裝修','阿曼空間設計','尚藝室內裝修','富億空間設計','齊舍設計','大琚空間設計','將作空間','昱承室內裝修','YHS DESIGN','德本迪室內設計','森境王俊宏設計','綵韻室內設計','寓子設計','東風室內設計','陶璽空間設計','惹雅國際設計','藝谷空間設計']
+qlist=['上築空間設計','豐聚室內裝修','富億空間設計','浩室設計','京璽國際','IS國際設計','優尼客','摩登雅舍','亞維空間設計','比沙列','富億設計','豐聚設計']
+#qlist=['春雨時尚空間','萬寶隆空間設計','含仰空間設計','綵韻室內設計','雅典設計','境庭國際設計','張馨室內設計','尚藝室內裝修','豐聚室內裝修','阿曼空間設計','尚藝室內裝修','富億空間設計','齊舍設計','大琚空間設計','將作空間','昱承室內裝修','YHS DESIGN','德本迪室內設計','森境王俊宏設計','綵韻室內設計','寓子設計','東風室內設計','陶璽空間設計','惹雅國際設計','藝谷空間設計']
 
 while True:
     q=random.choice(qlist)

+ 18 - 14
hhh/gen_customer_list.py

@@ -4,29 +4,33 @@ import csv
 import dataset
 import datetime
 
-db = dataset.connect('sqlite:///c:/tmp/hhh.db')
-table=db['monitor_list']
+db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/hhh?charset=utf8mb4')
+
+#db = dataset.connect('sqlite:///c:/tmp/hhh.db')
+table=db['customer_list']
 print (os.getcwd())
 print(os.path.realpath('.'))
 
-qlist=['元均制作','三宅一秀','采品室內設計','綵韻室內設計','春雨時尚空間','阿曼空間設計' \
-,'雅典設計','境庭國際設計','豐聚室內裝修','張馨室內設計','尚藝室內裝修','富億空間設計', \
-    '比沙列室內裝修','森境王俊宏設計','格綸設計','齊舍設計','采舍空間設計','大琚空間設計' \
-,'將作空間','昱承室內裝修','YHS DESIGN','德本迪室內設計','東風室內設計'  \
-, '陶璽空間設計','惹雅國際設計','浩室設計','藝谷空間設計','IS國際設計' \
-, '摩登雅舍室內','星葉室內裝修','浩室設計','演拓空間','千綵胤空間' \
-, '京璽國際','元典設計','朱英凱室內設計','亞維空間設計','馥築時尚設計' \
-, '文儀室內裝修','寓子設計','恆岳空間設計','卓林室內設計','歐德傢俱' \
-, '大久空間設計','成綺空間設計','知域設計','尚展空間設計','演繹動線空間' \
-, '苡希創意設計','玖柞設計','維耕設計','昱森室內設計','上築空間設計' \
-, 'HATCH合砌設計','至文室內裝修','上陽設計','禾禾設計','聯寬室內裝修']
+qlist=['IS國際設計','三宅一秀','元均制作','格倫','浩室設計','富億空間設計','雅典設計','雲方','豐聚室內裝修','上築空間設計','京璽國際','采品室內設計','恆岳空間設計','唐林設計','摩登雅舍','澤序','優尼客','允庭','比沙列','禾亞設計','禾築','我思空間','沛沛設計','亞維','恆岳','格綸']
+
+#qlist=['元均制作','三宅一秀','采品室內設計','綵韻室內設計','春雨時尚空間','阿曼空間設計' \
+#,'雅典設計','境庭國際設計','豐聚室內裝修','張馨室內設計','尚藝室內裝修','富億空間設計', \
+#    '比沙列室內裝修','森境王俊宏設計','格綸設計','齊舍設計','采舍空間設計','大琚空間設計' \
+#,'將作空間','昱承室內裝修','YHS DESIGN','德本迪室內設計','東風室內設計'  \
+#, '陶璽空間設計','惹雅國際設計','浩室設計','藝谷空間設計','IS國際設計' \
+#, '摩登雅舍室內','星葉室內裝修','浩室設計','演拓空間','千綵胤空間' \
+#, '京璽國際','元典設計','朱英凱室內設計','亞維空間設計','馥築時尚設計' \
+#, '文儀室內裝修','寓子設計','恆岳空間設計','卓林室內設計','歐德傢俱' \
+#, '大久空間設計','成綺空間設計','知域設計','尚展空間設計','演繹動線空間' \
+#, '苡希創意設計','玖柞設計','維耕設計','昱森室內設計','上築空間設計' \
+#, 'HATCH合砌設計','至文室內裝修','上陽設計','禾禾設計','聯寬室內裝修']
 
 
 for q in qlist:
     table.upsert({'name':q,'updated':datetime.datetime.now()},keys=['name'])
 
 
-cursor=db.query('select * from monitor_list')
+cursor=db.query('select * from customer_list')
 for c in cursor:
     print(c['name'])
     print(c['updated'])

+ 102 - 0
hhh/gen_designer_report.py

@@ -0,0 +1,102 @@
+from typing import NoReturn
+from selenium import webdriver
+import time
+import networkx as nx
+import dataset
+import pickle
+import codecs
+import sys
+import os
+import time
+import re
+import pandas as pd
+import datetime
+import dataset
+import jinja2
+
+db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/hhh?charset=utf8mb4')
+fname=os.path.abspath(__file__)
+elmts=fname.split(os.path.sep)
+path2=os.path.sep.join(elmts[0:-1])
+keysdir=path2+os.path.sep+'static'+os.path.sep
+
+
+
+
+templateLoader = jinja2.FileSystemLoader(searchpath=keysdir)
+templateEnv = jinja2.Environment(loader=templateLoader)
+TEMPLATE_FILE = "designer.tmpl"
+template = templateEnv.get_template(TEMPLATE_FILE)
+
+repeat={}
+displaydata=[]
+cursor=db.query('SELECT designer,searchome,c_100,hhh,dt FROM hhh.rank_summary order by dt desc,hhh asc;')
+for c in cursor:
+    designer=c['designer']
+    if repeat.get(designer) is None:
+        repeat[designer]=1
+        hhh=c['hhh']
+        c_100=c['c_100']
+        searchome=c['searchome']
+        hhh_label='<a  href="https://www.google.com/search?q='+designer+'"><button class="btn btn-primary">幸福空間 <span class="badge">'+str(c['hhh'])+'</span> </button></a>'
+
+        if c_100==-1:
+            c100_label='<span>&nbsp;</span>'
+        else:
+#            sch_label='<span>設計家('+str(c['searchome'])+')</span>'
+            c100_label='<a  href="https://www.google.com/search?q='+designer+'"><button class="btn btn-danger">100設計 <span class="badge">'+str(c['c_100'])+'</span> </button></a>'
+
+
+
+        if searchome==-1:
+            sch_label='<span>&nbsp;</span>'
+        else:
+#            sch_label='<span>設計家('+str(c['searchome'])+')</span>'
+            sch_label='<a  href="https://www.google.com/search?q='+designer+'"><button class="btn btn-danger">設計家 <span class="badge">'+str(c['searchome'])+'</span> </button></a>'
+
+
+        local_lst=[]
+        if hhh > 0:
+            local_lst.append(('hhh',hhh))
+        if searchome > 0:
+            local_lst.append(('searchome',searchome))
+        if c_100 > 0:
+            local_lst.append(('c_100',c_100))
+
+        sorted_by_second = sorted(local_lst, key=lambda tup: tup[1])
+        print(sorted_by_second)
+#        local_lst.sort()
+#        if hhh<searchome:
+#            first=hhh_label
+#            if searchome >0:
+#                if c_100>0:
+#                    if c_100 < searchome
+#            second=sch_label
+#        else:
+        first=None
+        second=None
+        slen=len(sorted_by_second)
+        
+        results=[]
+        for l in sorted_by_second:
+            if l[0]=='hhh':
+                results.append(hhh_label)
+            if l[0]=='searchome':
+                results.append(sch_label)
+            if l[0]=='c_100':
+                results.append(c100_label)
+
+        if slen==1:
+            results.append('<span>&nbsp;</span>')
+
+        displaydata.append({'designer':designer,'first':results[0],'second':results[1],'dt':c['dt']})
+#
+#displaydata=[{'a':'aaa','b':'bbb','c':'ccc'},{'a':'aaa2','b':'bbb2','c':'ccc2'}]
+outputText = template.render(displaydata=displaydata) 
+
+fw=codecs.open('c:/tmp/output.html','w','utf-8')
+fw.write(outputText)
+fw.close()
+os.startfile('c:/tmp/output.html')
+
+print(outputText)

+ 203 - 0
hhh/google_kw_test.py

@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+# Copyright 2019 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""This example generates keyword ideas from a list of seed keywords."""
+
+
+import argparse
+import sys
+from google.ads.googleads.client import GoogleAdsClient
+from google.ads.googleads.errors import GoogleAdsException
+
+# Location IDs are listed here:
+# https://developers.google.com/google-ads/api/reference/data/geotargets
+# and they can also be retrieved using the GeoTargetConstantService as shown
+# here: https://developers.google.com/google-ads/api/docs/targeting/location-targeting
+_DEFAULT_LOCATION_IDS = ["1023191"]  # location ID for New York, NY
+# A language criterion ID. For example, specify 1000 for English. For more
+# information on determining this value, see the below link:
+# https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7
+_DEFAULT_LANGUAGE_ID = "1000"  # language ID for English
+
+
+# [START generate_keyword_ideas]
+def main(
+    client, customer_id, location_ids, language_id, keyword_texts, page_url
+):
+    keyword_plan_idea_service = client.get_service("KeywordPlanIdeaService")
+    keyword_competition_level_enum = client.get_type(
+        "KeywordPlanCompetitionLevelEnum"
+    ).KeywordPlanCompetitionLevel
+    keyword_plan_network = client.get_type(
+        "KeywordPlanNetworkEnum"
+    ).KeywordPlanNetwork.GOOGLE_SEARCH_AND_PARTNERS
+    location_rns = _map_locations_ids_to_resource_names(client, location_ids)
+    language_rn = client.get_service(
+        "LanguageConstantService"
+    ).language_constant_path(language_id)
+
+    # Either keywords or a page_url are required to generate keyword ideas
+    # so this raises an error if neither are provided.
+    if not (keyword_texts or page_url):
+        raise ValueError(
+            "At least one of keywords or page URL is required, "
+            "but neither was specified."
+        )
+
+    # Only one of the fields "url_seed", "keyword_seed", or
+    # "keyword_and_url_seed" can be set on the request, depending on whether
+    # keywords, a page_url or both were passed to this function.
+    request = client.get_type("GenerateKeywordIdeasRequest")
+    request.customer_id = customer_id
+    request.language = language_rn
+    request.geo_target_constants = location_rns
+    request.include_adult_keywords = False
+    request.keyword_plan_network = keyword_plan_network
+
+    # To generate keyword ideas with only a page_url and no keywords we need
+    # to initialize a UrlSeed object with the page_url as the "url" field.
+    if not keyword_texts and page_url:
+        request.url_seed.url = page_url
+
+    # To generate keyword ideas with only a list of keywords and no page_url
+    # we need to initialize a KeywordSeed object and set the "keywords" field
+    # to be a list of StringValue objects.
+    if keyword_texts and not page_url:
+        request.keyword_seed.keywords.extend(keyword_texts)
+
+    # To generate keyword ideas using both a list of keywords and a page_url we
+    # need to initialize a KeywordAndUrlSeed object, setting both the "url" and
+    # "keywords" fields.
+    if keyword_texts and page_url:
+        request.keyword_and_url_seed.url = page_url
+        request.keyword_and_url_seed.keywords.extend(keyword_texts)
+
+    keyword_ideas = keyword_plan_idea_service.generate_keyword_ideas(
+        request=request
+    )
+
+    for idea in keyword_ideas:
+        competition_value = idea.keyword_idea_metrics.competition.name
+        print(
+            f'Keyword idea text "{idea.text}" has '
+            f'"{idea.keyword_idea_metrics.avg_monthly_searches}" '
+            f'average monthly searches and "{competition_value}" '
+            "competition.\n"
+        )
+    # [END generate_keyword_ideas]
+
+
+def map_keywords_to_string_values(client, keyword_texts):
+    keyword_protos = []
+    for keyword in keyword_texts:
+        string_val = client.get_type("StringValue")
+        string_val.value = keyword
+        keyword_protos.append(string_val)
+    return keyword_protos
+
+
+def _map_locations_ids_to_resource_names(client, location_ids):
+    """Converts a list of location IDs to resource names.
+
+    Args:
+        client: an initialized GoogleAdsClient instance.
+        location_ids: a list of location ID strings.
+
+    Returns:
+        a list of resource name strings using the given location IDs.
+    """
+    build_resource_name = client.get_service(
+        "GeoTargetConstantService"
+    ).geo_target_constant_path
+    return [build_resource_name(location_id) for location_id in location_ids]
+
+
+if __name__ == "__main__":
+    # GoogleAdsClient will read the google-ads.yaml configuration file in the
+    # home directory if none is specified.
+    googleads_client = GoogleAdsClient.load_from_storage(version="v7")
+
+    parser = argparse.ArgumentParser(
+        description="Generates keyword ideas from a list of seed keywords."
+    )
+
+    # The following argument(s) should be provided to run the example.
+    parser.add_argument(
+        "-c",
+        "--customer_id",
+        type=str,
+        required=True,
+        help="The Google Ads customer ID.",
+    )
+    parser.add_argument(
+        "-k",
+        "--keyword_texts",
+        nargs="+",
+        type=str,
+        required=False,
+        default=[],
+        help="Space-delimited list of starter keywords",
+    )
+    # To determine the appropriate location IDs, see:
+    # https://developers.google.com/google-ads/api/reference/data/geotargets
+    parser.add_argument(
+        "-l",
+        "--location_ids",
+        nargs="+",
+        type=str,
+        required=False,
+        default=_DEFAULT_LOCATION_IDS,
+        help="Space-delimited list of location criteria IDs",
+    )
+    # To determine the appropriate language ID, see:
+    # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7
+    parser.add_argument(
+        "-i",
+        "--language_id",
+        type=str,
+        required=False,
+        default=_DEFAULT_LANGUAGE_ID,
+        help="The language criterion ID.",
+    )
+    # Optional: Specify a URL string related to your business to generate ideas.
+    parser.add_argument(
+        "-p",
+        "--page_url",
+        type=str,
+        required=False,
+        help="A URL string related to your business",
+    )
+
+    args = parser.parse_args()
+
+    try:
+        main(
+            googleads_client,
+            args.customer_id,
+            args.location_ids,
+            args.language_id,
+            args.keyword_texts,
+            args.page_url,
+        )
+    except GoogleAdsException as ex:
+        print(
+            f'Request with ID "{ex.request_id}" failed with status '
+            f'"{ex.error.code().name}" and includes the following errors:'
+        )
+        for error in ex.failure.errors:
+            print(f'\tError with message "{error.message}".')
+            if error.location:
+                for field_path_element in error.location.field_path_elements:
+                    print(f"\t\tOn field: {field_path_element.field_name}")
+        sys.exit(1)

+ 423 - 0
hhh/static/admin.html

@@ -0,0 +1,423 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <meta name="description" content="">
+    <meta name="author" content="">
+
+    <title>SB Admin 2 - Dashboard</title>
+
+    <!-- Custom fonts for this template-->
+    <link href="/static/css/all.min.css" rel="stylesheet" type="text/css">
+    <link
+        href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
+        rel="stylesheet">
+
+    <!-- Custom styles for this template-->
+    <link href="/static/css/sb-admin-2.min.css" rel="stylesheet">
+
+</head>
+
+<body id="page-top">
+
+    <!-- Page Wrapper -->
+    <div id="wrapper">
+
+        <!-- Sidebar -->
+        <ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
+
+            <!-- Sidebar - Brand -->
+            <a class="sidebar-brand d-flex align-items-center justify-content-center" href="index.html">
+                <div class="sidebar-brand-icon rotate-n-15">
+                    <i class="fas fa-laugh-wink"></i>
+                </div>
+                <div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
+            </a>
+
+            <!-- Divider -->
+            <hr class="sidebar-divider my-0">
+
+            <!-- Nav Item - Dashboard -->
+            <li class="nav-item active">
+                <a class="nav-link" href="index.html">
+                    <i class="fas fa-fw fa-tachometer-alt"></i>
+                    <span>Dashboard</span></a>
+            </li>
+
+            <!-- Divider -->
+            <hr class="sidebar-divider">
+
+            <!-- Heading -->
+            <div class="sidebar-heading">
+                Interface
+            </div>
+
+            <!-- Nav Item - Pages Collapse Menu -->
+            <li class="nav-item">
+                <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
+                    aria-expanded="true" aria-controls="collapseTwo">
+                    <i class="fas fa-fw fa-cog"></i>
+                    <span>Components</span>
+                </a>
+                <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
+                    <div class="bg-white py-2 collapse-inner rounded">
+                        <h6 class="collapse-header">Custom Components:</h6>
+                        <a class="collapse-item" href="buttons.html">Buttons</a>
+                        <a class="collapse-item" href="cards.html">Cards</a>
+                    </div>
+                </div>
+            </li>
+
+            <!-- Nav Item - Utilities Collapse Menu -->
+            <li class="nav-item">
+                <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
+                    aria-expanded="true" aria-controls="collapseUtilities">
+                    <i class="fas fa-fw fa-wrench"></i>
+                    <span>Utilities</span>
+                </a>
+                <div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
+                    data-parent="#accordionSidebar">
+                    <div class="bg-white py-2 collapse-inner rounded">
+                        <h6 class="collapse-header">Custom Utilities:</h6>
+                        <a class="collapse-item" href="utilities-color.html">Colors</a>
+                        <a class="collapse-item" href="utilities-border.html">Borders</a>
+                        <a class="collapse-item" href="utilities-animation.html">Animations</a>
+                        <a class="collapse-item" href="utilities-other.html">Other</a>
+                    </div>
+                </div>
+            </li>
+
+            <!-- Divider -->
+            <hr class="sidebar-divider">
+
+            <!-- Heading -->
+            <div class="sidebar-heading">
+                Addons
+            </div>
+
+            <!-- Nav Item - Pages Collapse Menu -->
+            <li class="nav-item">
+                <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
+                    aria-expanded="true" aria-controls="collapsePages">
+                    <i class="fas fa-fw fa-folder"></i>
+                    <span>Pages</span>
+                </a>
+                <div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
+                    <div class="bg-white py-2 collapse-inner rounded">
+                        <h6 class="collapse-header">Login Screens:</h6>
+                        <a class="collapse-item" href="login.html">Login</a>
+                        <a class="collapse-item" href="register.html">Register</a>
+                        <a class="collapse-item" href="forgot-password.html">Forgot Password</a>
+                        <div class="collapse-divider"></div>
+                        <h6 class="collapse-header">Other Pages:</h6>
+                        <a class="collapse-item" href="404.html">404 Page</a>
+                        <a class="collapse-item" href="blank.html">Blank Page</a>
+                    </div>
+                </div>
+            </li>
+
+            <!-- Nav Item - Charts -->
+            <li class="nav-item">
+                <a class="nav-link" href="charts.html">
+                    <i class="fas fa-fw fa-chart-area"></i>
+                    <span>Charts</span></a>
+            </li>
+
+            <!-- Nav Item - Tables -->
+            <li class="nav-item">
+                <a class="nav-link" href="tables.html">
+                    <i class="fas fa-fw fa-table"></i>
+                    <span>Tables</span></a>
+            </li>
+
+            <!-- Divider -->
+            <hr class="sidebar-divider d-none d-md-block">
+
+            <!-- Sidebar Toggler (Sidebar) -->
+            <div class="text-center d-none d-md-inline">
+                <button class="rounded-circle border-0" id="sidebarToggle"></button>
+            </div>
+
+            <!-- Sidebar Message -->
+
+        </ul>
+        <!-- End of Sidebar -->
+
+        <!-- Content Wrapper -->
+        <div id="content-wrapper" class="d-flex flex-column">
+
+            <!-- Main Content -->
+            <div id="content">
+
+                <!-- Topbar -->
+                <nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
+
+                    <!-- Sidebar Toggle (Topbar) -->
+                    <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
+                        <i class="fa fa-bars"></i>
+                    </button>
+
+                    <!-- Topbar Search -->
+                    <form
+                        class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
+                        <div class="input-group">
+                            <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
+                                aria-label="Search" aria-describedby="basic-addon2">
+                            <div class="input-group-append">
+                                <button class="btn btn-primary" type="button">
+                                    <i class="fas fa-search fa-sm"></i>
+                                </button>
+                            </div>
+                        </div>
+                    </form>
+
+                    <!-- Topbar Navbar -->
+                    <ul class="navbar-nav ml-auto">
+
+                        <!-- Nav Item - Search Dropdown (Visible Only XS) -->
+                        <li class="nav-item dropdown no-arrow d-sm-none">
+                            <a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
+                                data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                <i class="fas fa-search fa-fw"></i>
+                            </a>
+                            <!-- Dropdown - Messages -->
+                            <div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
+                                aria-labelledby="searchDropdown">
+                                <form class="form-inline mr-auto w-100 navbar-search">
+                                    <div class="input-group">
+                                        <input type="text" class="form-control bg-light border-0 small"
+                                            placeholder="Search for..." aria-label="Search"
+                                            aria-describedby="basic-addon2">
+                                        <div class="input-group-append">
+                                            <button class="btn btn-primary" type="button">
+                                                <i class="fas fa-search fa-sm"></i>
+                                            </button>
+                                        </div>
+                                    </div>
+                                </form>
+                            </div>
+                        </li>
+
+                        <!-- Nav Item - Alerts -->
+                        <li class="nav-item dropdown no-arrow mx-1">
+                            <a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
+                                data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                <i class="fas fa-bell fa-fw"></i>
+                                <!-- Counter - Alerts -->
+                                <span class="badge badge-danger badge-counter">3+</span>
+                            </a>
+                            <!-- Dropdown - Alerts -->
+                            <div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
+                                aria-labelledby="alertsDropdown">
+                                <h6 class="dropdown-header">
+                                    Alerts Center
+                                </h6>
+                                <a class="dropdown-item d-flex align-items-center" href="#">
+                                    <div class="mr-3">
+                                        <div class="icon-circle bg-primary">
+                                            <i class="fas fa-file-alt text-white"></i>
+                                        </div>
+                                    </div>
+                                    <div>
+                                        <div class="small text-gray-500">December 12, 2019</div>
+                                        <span class="font-weight-bold">A new monthly report is ready to download!</span>
+                                    </div>
+                                </a>
+                                <a class="dropdown-item d-flex align-items-center" href="#">
+                                    <div class="mr-3">
+                                        <div class="icon-circle bg-success">
+                                            <i class="fas fa-donate text-white"></i>
+                                        </div>
+                                    </div>
+                                    <div>
+                                        <div class="small text-gray-500">December 7, 2019</div>
+                                        $290.29 has been deposited into your account!
+                                    </div>
+                                </a>
+                                <a class="dropdown-item d-flex align-items-center" href="#">
+                                    <div class="mr-3">
+                                        <div class="icon-circle bg-warning">
+                                            <i class="fas fa-exclamation-triangle text-white"></i>
+                                        </div>
+                                    </div>
+                                    <div>
+                                        <div class="small text-gray-500">December 2, 2019</div>
+                                        Spending Alert: We've noticed unusually high spending for your account.
+                                    </div>
+                                </a>
+                                <a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
+                            </div>
+                        </li>
+
+                        <!-- Nav Item - Messages -->
+                        <li class="nav-item dropdown no-arrow mx-1">
+                            <a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
+                                data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                <i class="fas fa-envelope fa-fw"></i>
+                                <!-- Counter - Messages -->
+                                <span class="badge badge-danger badge-counter">7</span>
+                            </a>
+                            <!-- Dropdown - Messages -->
+                            <div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
+                                aria-labelledby="messagesDropdown">
+                                <h6 class="dropdown-header">
+                                    Message Center
+                                </h6>
+                                <a class="dropdown-item d-flex align-items-center" href="#">
+                                    <div class="dropdown-list-image mr-3">
+                                        <img class="rounded-circle" src="img/undraw_profile_1.svg"
+                                            alt="...">
+                                        <div class="status-indicator bg-success"></div>
+                                    </div>
+                                    <div class="font-weight-bold">
+                                        <div class="text-truncate">Hi there! I am wondering if you can help me with a
+                                            problem I've been having.</div>
+                                        <div class="small text-gray-500">Emily Fowler · 58m</div>
+                                    </div>
+                                </a>
+                                <a class="dropdown-item d-flex align-items-center" href="#">
+                                    <div class="dropdown-list-image mr-3">
+                                        <img class="rounded-circle" src="img/undraw_profile_2.svg"
+                                            alt="...">
+                                        <div class="status-indicator"></div>
+                                    </div>
+                                    <div>
+                                        <div class="text-truncate">I have the photos that you ordered last month, how
+                                            would you like them sent to you?</div>
+                                        <div class="small text-gray-500">Jae Chun · 1d</div>
+                                    </div>
+                                </a>
+                                <a class="dropdown-item d-flex align-items-center" href="#">
+                                    <div class="dropdown-list-image mr-3">
+                                        <img class="rounded-circle" src="img/undraw_profile_3.svg"
+                                            alt="...">
+                                        <div class="status-indicator bg-warning"></div>
+                                    </div>
+                                    <div>
+                                        <div class="text-truncate">Last month's report looks great, I am very happy with
+                                            the progress so far, keep up the good work!</div>
+                                        <div class="small text-gray-500">Morgan Alvarez · 2d</div>
+                                    </div>
+                                </a>
+                                <a class="dropdown-item d-flex align-items-center" href="#">
+                                    <div class="dropdown-list-image mr-3">
+                                        <img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
+                                            alt="...">
+                                        <div class="status-indicator bg-success"></div>
+                                    </div>
+                                    <div>
+                                        <div class="text-truncate">Am I a good boy? The reason I ask is because someone
+                                            told me that people say this to all dogs, even if they aren't good...</div>
+                                        <div class="small text-gray-500">Chicken the Dog · 2w</div>
+                                    </div>
+                                </a>
+                                <a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
+                            </div>
+                        </li>
+
+                        <div class="topbar-divider d-none d-sm-block"></div>
+
+                        <!-- Nav Item - User Information -->
+                        <li class="nav-item dropdown no-arrow">
+                            <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
+                                data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+								<!-- user
+                                <span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
+								-->
+                                <img class="img-profile rounded-circle"
+                                    src="img/undraw_profile.svg">
+									
+                            </a>
+                            <!-- Dropdown - User Information -->
+                            <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
+                                aria-labelledby="userDropdown">
+                                <a class="dropdown-item" href="#">
+                                    <i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
+                                    Profile
+                                </a>
+                                <a class="dropdown-item" href="#">
+                                    <i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
+                                    Settings
+                                </a>
+                                <a class="dropdown-item" href="#">
+                                    <i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
+                                    Activity Log
+                                </a>
+                                <div class="dropdown-divider"></div>
+                                <a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
+                                    <i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
+                                    Logout
+                                </a>
+                            </div>
+                        </li>
+
+                    </ul>
+
+                </nav>
+                <!-- End of Topbar -->
+
+                <!-- Begin Page Content -->
+                
+
+            </div>
+            <!-- End of Main Content -->
+
+            <!-- Footer -->
+            <footer class="sticky-footer bg-white">
+                <div class="container my-auto">
+                    <div class="copyright text-center my-auto">
+                        <span>Copyright &copy; Your Website 2021</span>
+                    </div>
+                </div>
+            </footer>
+            <!-- End of Footer -->
+
+        </div>
+        <!-- End of Content Wrapper -->
+
+    </div>
+    <!-- End of Page Wrapper -->
+
+    <!-- Scroll to Top Button-->
+    <a class="scroll-to-top rounded" href="#page-top">
+        <i class="fas fa-angle-up"></i>
+    </a>
+
+    <!-- Logout Modal-->
+    <div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
+        aria-hidden="true">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
+                    <button class="close" type="button" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
+                <div class="modal-footer">
+                    <button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
+                    <a class="btn btn-primary" href="login.html">Logout</a>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- Bootstrap core JavaScript-->
+    <script src="/static/js/jquery.min.js"></script>
+    <script src="/static/js/bootstrap.bundle.min.js"></script>
+
+    <!-- Core plugin JavaScript-->
+    <script src="/static/js/jquery.easing.min.js"></script>
+
+    <!-- Custom scripts for all pages-->
+    <script src="/static/js/sb-admin-2.min.js"></script>
+
+
+</body>
+
+</html>

File diff suppressed because it is too large
+ 4 - 0
hhh/static/css/all.min.css


File diff suppressed because it is too large
+ 9 - 0
hhh/static/css/sb-admin-2.min.css


File diff suppressed because it is too large
+ 5 - 0
hhh/static/js/bootstrap.bundle.min.js


File diff suppressed because it is too large
+ 0 - 0
hhh/static/js/jquery.easing.min.js


File diff suppressed because it is too large
+ 1 - 0
hhh/static/js/jquery.min.js


+ 7 - 0
hhh/static/js/sb-admin-2.min.js

@@ -0,0 +1,7 @@
+/*!
+ * Start Bootstrap - SB Admin 2 v4.1.3 (https://startbootstrap.com/theme/sb-admin-2)
+ * Copyright 2013-2021 Start Bootstrap
+ * Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-sb-admin-2/blob/master/LICENSE)
+ */
+
+!function(l){"use strict";l("#sidebarToggle, #sidebarToggleTop").on("click",function(e){l("body").toggleClass("sidebar-toggled"),l(".sidebar").toggleClass("toggled"),l(".sidebar").hasClass("toggled")&&l(".sidebar .collapse").collapse("hide")}),l(window).resize(function(){l(window).width()<768&&l(".sidebar .collapse").collapse("hide"),l(window).width()<480&&!l(".sidebar").hasClass("toggled")&&(l("body").addClass("sidebar-toggled"),l(".sidebar").addClass("toggled"),l(".sidebar .collapse").collapse("hide"))}),l("body.fixed-nav .sidebar").on("mousewheel DOMMouseScroll wheel",function(e){var o;768<l(window).width()&&(o=(o=e.originalEvent).wheelDelta||-o.detail,this.scrollTop+=30*(o<0?1:-1),e.preventDefault())}),l(document).on("scroll",function(){100<l(this).scrollTop()?l(".scroll-to-top").fadeIn():l(".scroll-to-top").fadeOut()}),l(document).on("click","a.scroll-to-top",function(e){var o=l(this);l("html, body").stop().animate({scrollTop:l(o.attr("href")).offset().top},1e3,"easeInOutExpo"),e.preventDefault()})}(jQuery);

+ 147 - 0
hhh/static/test.html

@@ -0,0 +1,147 @@
+<html>
+    <head>
+        <link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css'>
+<style>
+body {
+  background-color: #bdc3c7;
+}
+
+.table-fixed {
+  width: 100%;
+  background-color: #f3f3f3;
+}
+.table-fixed tbody {
+  height: 200px;
+  overflow-y: auto;
+  width: 100%;
+}
+.table-fixed thead, .table-fixed tbody, .table-fixed tr, .table-fixed td, .table-fixed th {
+  display: block;
+}
+.table-fixed tbody td {
+  float: left;
+}
+.table-fixed thead tr th {
+  float: left;
+  background-color: #f39c12;
+  border-color: #e67e22;
+}
+</style>
+    </head>
+<body>
+    <div class="container">
+        <table class="table table-fixed">
+          <thead>
+            <tr>
+              <th class="col-xs-3">First Name</th>
+              <th class="col-xs-3">Last Name</th>
+              <th class="col-xs-6">E-mail</th>
+            </tr>
+          </thead>
+          <tbody>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+      
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+            <tr>
+              <td class="col-xs-3">John</td>
+              <td class="col-xs-3">Doe</td>
+              <td class="col-xs-6">johndoe@email.com</td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+</body>
+</html>

Some files were not shown because too many files changed in this diff