From a9d86650f40a82a64d1fd8e0525c26422d314d3a Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 16 Mar 2021 16:38:07 +0100 Subject: make uploads like animism. start audio stuff --- .../202103161637_make_uploads_like_on_animism.py | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 cli/app/sql/versions/202103161637_make_uploads_like_on_animism.py (limited to 'cli/app/sql/versions') diff --git a/cli/app/sql/versions/202103161637_make_uploads_like_on_animism.py b/cli/app/sql/versions/202103161637_make_uploads_like_on_animism.py new file mode 100644 index 0000000..18bf0bc --- /dev/null +++ b/cli/app/sql/versions/202103161637_make_uploads_like_on_animism.py @@ -0,0 +1,31 @@ +"""make uploads like on animism + +Revision ID: 645f315e651d +Revises: d929da3e398b +Create Date: 2021-03-16 16:37:08.985792 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utc + + +# revision identifiers, used by Alembic. +revision = '645f315e651d' +down_revision = 'd929da3e398b' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('upload', sa.Column('graph_id', sa.Integer(), nullable=True)) + op.add_column('upload', sa.Column('tag', sa.String(length=64, _expect_unicode=True), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('upload', 'tag') + op.drop_column('upload', 'graph_id') + # ### end Alembic commands ### -- cgit v1.2.3-70-g09d2 From 1cfe96ca6ef5c54eadd986c951dade0f56d72440 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 16 Mar 2021 16:54:28 +0100 Subject: migrating to mysql --- cli/app/settings/app_cfg.py | 6 ++ cli/app/sql/common.py | 23 ++-- cli/app/sql/env.py | 2 +- cli/app/sql/models/graph.py | 3 + cli/app/sql/models/upload.py | 4 +- .../202103161645_add_foreign_key_constraint.py | 29 +++++ cli/commands/admin/migrate_to_mysql.py | 120 +++++++++++++++++++++ docs/migrate_to_mysql.md | 1 + env-sample | 7 ++ frontend/app/views/index/containers/graph.index.js | 1 + 10 files changed, 181 insertions(+), 15 deletions(-) create mode 100644 cli/app/sql/versions/202103161645_add_foreign_key_constraint.py create mode 100644 cli/commands/admin/migrate_to_mysql.py create mode 100644 docs/migrate_to_mysql.md (limited to 'cli/app/sql/versions') diff --git a/cli/app/settings/app_cfg.py b/cli/app/settings/app_cfg.py index 3865abd..af6cf89 100644 --- a/cli/app/settings/app_cfg.py +++ b/cli/app/settings/app_cfg.py @@ -33,6 +33,7 @@ load_dotenv(dotenv_path=fp_env) CLICK_GROUPS = { # 'process': 'commands/process', 'site': 'commands/site', + 'admin': 'commands/admin', 'db': '', 'flask': '', } @@ -65,6 +66,11 @@ HASH_BRANCH_SIZE = 3 # for sha256 subdirs DIR_PUBLIC_EXPORTS = os.getenv('DIR_PUBLIC_EXPORTS') or DIR_EXPORTS +# ----------------------------------------------------------------------------- +# Database +# ----------------------------------------------------------------------------- + +USE_SQLITE = os.getenv("USE_SQLITE") == "True" # ----------------------------------------------------------------------------- # S3 storage diff --git a/cli/app/sql/common.py b/cli/app/sql/common.py index c8bd557..8e1d2b3 100644 --- a/cli/app/sql/common.py +++ b/cli/app/sql/common.py @@ -2,7 +2,6 @@ import os import glob import time -# import mysql.connector from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base @@ -11,16 +10,16 @@ from flask_sqlalchemy import SQLAlchemy from app.settings import app_cfg -# connection_url = "mysql+mysqlconnector://{}:{}@{}/{}?charset=utf8mb4".format( -# os.getenv("DB_USER"), -# os.getenv("DB_PASS"), -# os.getenv("DB_HOST"), -# os.getenv("DB_NAME") -# ) - -os.makedirs(app_cfg.DIR_DATABASE, exist_ok=True) - -connection_url = "sqlite:///{}".format(os.path.join(app_cfg.DIR_DATABASE, 'swimmer.sqlite3')) +if app_cfg.USE_SQLITE: + os.makedirs(app_cfg.DIR_DATABASE, exist_ok=True) + connection_url = "sqlite:///{}".format(os.path.join(app_cfg.DIR_DATABASE, 'swimmer.sqlite3')) +else: + connection_url = "mysql+pymysql://{}:{}@{}/{}?charset=utf8mb4".format( + os.getenv("DB_USER"), + os.getenv("DB_PASS"), + os.getenv("DB_HOST"), + os.getenv("DB_NAME") + ) engine = create_engine(connection_url, encoding="utf-8", pool_recycle=3600) @@ -31,7 +30,7 @@ Base.metadata.bind = engine db = SQLAlchemy() # include the models in reverse dependency order, so relationships work +from app.sql.models.upload import Upload from app.sql.models.tile import Tile from app.sql.models.page import Page from app.sql.models.graph import Graph -from app.sql.models.upload import Upload diff --git a/cli/app/sql/env.py b/cli/app/sql/env.py index 7753565..3e015b5 100644 --- a/cli/app/sql/env.py +++ b/cli/app/sql/env.py @@ -14,10 +14,10 @@ config.set_main_option("sqlalchemy.url", connection_url) target_metadata = Base.metadata # include the models in reverse dependency order, so relationships work +from app.sql.models.upload import Upload from app.sql.models.tile import Tile from app.sql.models.page import Page from app.sql.models.graph import Graph -from app.sql.models.upload import Upload def run_migrations_offline(): """Run migrations in 'offline' mode. diff --git a/cli/app/sql/models/graph.py b/cli/app/sql/models/graph.py index 8e068a0..08f4d3c 100644 --- a/cli/app/sql/models/graph.py +++ b/cli/app/sql/models/graph.py @@ -23,6 +23,7 @@ class Graph(Base): updated_at = Column(UtcDateTime(), onupdate=utcnow()) pages = relationship('Page', lazy='dynamic') + uploads = relationship('Upload', lazy='dynamic') def toJSON(self): return { @@ -40,11 +41,13 @@ class Graph(Base): def toFullJSON(self): data = self.toJSON() data['pages'] = [ page.toLinkJSON() for page in self.pages ] + data['uploads'] = [ upload.toJSON() for upload in self.uploads ] return data def toSiteJSON(self): data = self.toJSON() data['pages'] = [ page.toFullJSON() for page in self.pages ] + data['uploads'] = [ upload.toJSON() for upload in self.uploads ] return data class GraphForm(ModelForm): diff --git a/cli/app/sql/models/upload.py b/cli/app/sql/models/upload.py index 87f758a..30e53dc 100644 --- a/cli/app/sql/models/upload.py +++ b/cli/app/sql/models/upload.py @@ -1,4 +1,4 @@ -from sqlalchemy import create_engine, Table, Column, String, Integer, DateTime +from sqlalchemy import create_engine, Table, Column, ForeignKey, String, Integer, DateTime import sqlalchemy.sql.functions as func from sqlalchemy_utc import UtcDateTime, utcnow from wtforms_alchemy import ModelForm @@ -14,7 +14,7 @@ class Upload(Base): """Table for storing references to various media""" __tablename__ = 'upload' id = Column(Integer, primary_key=True) - graph_id = Column(Integer) + graph_id = Column(Integer, ForeignKey('graph.id'), nullable=True) sha256 = Column(String(256), nullable=False) fn = Column(String(256), nullable=False) ext = Column(String(4, convert_unicode=True), nullable=False) diff --git a/cli/app/sql/versions/202103161645_add_foreign_key_constraint.py b/cli/app/sql/versions/202103161645_add_foreign_key_constraint.py new file mode 100644 index 0000000..673f9e4 --- /dev/null +++ b/cli/app/sql/versions/202103161645_add_foreign_key_constraint.py @@ -0,0 +1,29 @@ +"""add foreign key constraint + +Revision ID: 3f7df6bf63b8 +Revises: 645f315e651d +Create Date: 2021-03-16 16:45:39.455892 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utc + + +# revision identifiers, used by Alembic. +revision = '3f7df6bf63b8' +down_revision = '645f315e651d' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_foreign_key(None, 'upload', 'graph', ['graph_id'], ['id']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'upload', type_='foreignkey') + # ### end Alembic commands ### diff --git a/cli/commands/admin/migrate_to_mysql.py b/cli/commands/admin/migrate_to_mysql.py new file mode 100644 index 0000000..32ff7cf --- /dev/null +++ b/cli/commands/admin/migrate_to_mysql.py @@ -0,0 +1,120 @@ +import click +import os +import glob +import time + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.declarative import declarative_base + +from flask_sqlalchemy import SQLAlchemy + +from app.settings import app_cfg + +@click.command('migrate_to_mysql') +@click.pass_context +def cli(ctx): + """ + - Create connections to both databases + - For each table, for each row, insert from one to the other + """ + mysql_session, mysql_base = make_mysql_base() + sqlite_session, sqlite_base = make_sqlite3_base() + mysql_classes = make_classes(mysql_base) + sqlite_classes = make_classes(sqlite_base) + + for mysql_class, sqlite_class in zip(mysql_classes, sqlite_classes): + sqlite_objs = sqlite_session.query(sqlite_class).order_by(sqlite_class.id).all() + for sqlite_obj in sqlite_objs: + mysql_obj = mysql_class() + for column in sqlite_class.__table__.columns: + table_name, column_name = str(column).split(".") + # print(f"{table_name} => {column_name}") + # if column_name != 'id': + setattr(mysql_obj, column_name, getattr(sqlite_obj, column_name)) + mysql_session.add(mysql_obj) + mysql_session.commit() + +def make_mysql_base(): + """Make a Mysql connection""" + connection_url = "mysql+pymysql://{}:{}@{}/{}?charset=utf8mb4".format( + os.getenv("DB_USER"), + os.getenv("DB_PASS"), + os.getenv("DB_HOST"), + os.getenv("DB_NAME") + ) + return make_base(connection_url) + +def make_sqlite3_base(): + """Make a SQLite3 connection""" + connection_url = "sqlite:///{}".format(os.path.join(app_cfg.DIR_DATABASE, 'animism.sqlite3')) + return make_base(connection_url) + +def make_base(connection_url): + """Make a connection base from a connection URL""" + engine = create_engine(connection_url, encoding="utf-8", pool_recycle=3600) + Session = sessionmaker(bind=engine) + Base = declarative_base() + Base.metadata.bind = engine + db = SQLAlchemy() + return Session(), Base + +def make_classes(Base): + """Make classes from a base""" + + from sqlalchemy import create_engine, Table, Column, Text, String, Integer, \ + Boolean, Float, DateTime, JSON, ForeignKey + from sqlalchemy_utc import UtcDateTime, utcnow + + class Upload(Base): + """Table for storing references to various media""" + __tablename__ = 'upload' + id = Column(Integer, primary_key=True) + graph_id = Column(Integer, ForeignKey('graph.id'), nullable=True) + sha256 = Column(String(256), nullable=False) + fn = Column(String(256), nullable=False) + ext = Column(String(4, convert_unicode=True), nullable=False) + tag = Column(String(64, convert_unicode=True), nullable=True) + username = Column(String(16, convert_unicode=True), nullable=False) + created_at = Column(UtcDateTime(), default=utcnow()) + + class Tile(Base): + """Table for storing references to tiles""" + __tablename__ = 'tile' + id = Column(Integer, primary_key=True) + graph_id = Column(Integer, ForeignKey('graph.id'), nullable=True) + page_id = Column(Integer, ForeignKey('page.id'), nullable=True) + target_page_id = Column(Integer, ForeignKey('page.id'), nullable=True) + type = Column(String(16, convert_unicode=True), nullable=False) + sort_order = Column(Integer, default=0) + settings = Column(JSON, default={}, nullable=True) + created_at = Column(UtcDateTime(), default=utcnow()) + updated_at = Column(UtcDateTime(), onupdate=utcnow()) + + class Page(Base): + """Table for storing references to pages""" + __tablename__ = 'page' + id = Column(Integer, primary_key=True) + graph_id = Column(Integer, ForeignKey('graph.id'), nullable=True) + path = Column(String(64, convert_unicode=True), nullable=False) + title = Column(String(64, convert_unicode=True), nullable=False) + username = Column(String(32, convert_unicode=True), nullable=False) + description = Column(Text(convert_unicode=True), nullable=False) + settings = Column(JSON, default={}, nullable=True) + created_at = Column(UtcDateTime(), default=utcnow()) + updated_at = Column(UtcDateTime(), onupdate=utcnow()) + + class Graph(Base): + """Table for storing references to graphs""" + __tablename__ = 'graph' + id = Column(Integer, primary_key=True) + home_page_id = Column(Integer, nullable=True) + path = Column(String(64, convert_unicode=True), nullable=False) + title = Column(String(64, convert_unicode=True), nullable=False) + username = Column(String(32, convert_unicode=True), nullable=False) + description = Column(Text(convert_unicode=True), nullable=False) + settings = Column(JSON, default={}, nullable=True) + created_at = Column(UtcDateTime(), default=utcnow()) + updated_at = Column(UtcDateTime(), onupdate=utcnow()) + + return [ Upload, Graph, Page, Tile ] diff --git a/docs/migrate_to_mysql.md b/docs/migrate_to_mysql.md new file mode 100644 index 0000000..45fe7de --- /dev/null +++ b/docs/migrate_to_mysql.md @@ -0,0 +1 @@ +migrate_to_mysql.md diff --git a/env-sample b/env-sample index 1a23be3..83c36e4 100644 --- a/env-sample +++ b/env-sample @@ -2,3 +2,10 @@ FLASK_RUN_PORT=7500 SERVER_NAME=swim.neural.garden HTTP_EXTERNAL_HOST=https://swim.neural.garden +USE_SQLITE=False + +DB_USER=swimmer +DB_PASS= +DB_HOST=localhost +DB_NAME=swimmer + diff --git a/frontend/app/views/index/containers/graph.index.js b/frontend/app/views/index/containers/graph.index.js index 91098a7..bf3d75e 100644 --- a/frontend/app/views/index/containers/graph.index.js +++ b/frontend/app/views/index/containers/graph.index.js @@ -11,6 +11,7 @@ class GraphIndex extends Component { componentDidMount() { actions.graph.index() } + render() { const { index } = this.props // console.log(this.props) -- cgit v1.2.3-70-g09d2 From 50d5c3c2f10725af8ebb6db47c209f7000abc8f4 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sat, 20 Mar 2021 19:24:13 +0100 Subject: remove foreignkey constraint on target_page_id. toggle popups. show list of popups, if a tile link is open/close popup --- cli/app/sql/models/page.py | 6 ++-- cli/app/sql/models/tile.py | 2 +- ...03201916_remove_foreign_key_constraint_from_.py | 29 ++++++++++++++++++ frontend/app/types.js | 2 +- frontend/app/views/page/components/page.editor.js | 2 ++ frontend/app/views/page/page.actions.js | 14 +++++++++ frontend/app/views/page/page.container.js | 1 + frontend/app/views/page/page.reducer.js | 12 +++++++- frontend/app/views/tile/components/tile.form.js | 34 ++++++++++++++++++---- frontend/app/views/tile/components/tile.list.js | 4 +++ frontend/app/views/tile/components/tile.new.js | 1 + frontend/app/views/tile/handles/tile.link.js | 3 -- 12 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 cli/app/sql/versions/202103201916_remove_foreign_key_constraint_from_.py (limited to 'cli/app/sql/versions') diff --git a/cli/app/sql/models/page.py b/cli/app/sql/models/page.py index 2f7065b..35efa39 100644 --- a/cli/app/sql/models/page.py +++ b/cli/app/sql/models/page.py @@ -1,11 +1,11 @@ from sqlalchemy import create_engine, Table, Column, Text, String, Integer, DateTime, JSON, ForeignKey -from sqlalchemy.orm import relationship +from sqlalchemy.orm import relationship, foreign, remote import sqlalchemy.sql.functions as func from sqlalchemy_utc import UtcDateTime, utcnow from wtforms_alchemy import ModelForm from app.sql.common import db, Base, Session -# from app.sql.models.graph import Graph +from app.sql.models.tile import Tile from app.settings import app_cfg @@ -23,7 +23,7 @@ class Page(Base): updated_at = Column(UtcDateTime(), onupdate=utcnow()) tiles = relationship("Tile", foreign_keys="Tile.page_id", lazy='dynamic', order_by="asc(Tile.sort_order)") - backlinks = relationship("Tile", foreign_keys="Tile.target_page_id", lazy='dynamic') + backlinks = relationship("Tile", primaryjoin=id == foreign(Tile.target_page_id), lazy='dynamic') def toJSON(self): return { diff --git a/cli/app/sql/models/tile.py b/cli/app/sql/models/tile.py index 3f6ce31..ed4a5f8 100644 --- a/cli/app/sql/models/tile.py +++ b/cli/app/sql/models/tile.py @@ -18,7 +18,7 @@ class Tile(Base): id = Column(Integer, primary_key=True) graph_id = Column(Integer, ForeignKey('graph.id'), nullable=True) page_id = Column(Integer, ForeignKey('page.id'), nullable=True) - target_page_id = Column(Integer, ForeignKey('page.id'), nullable=True) + target_page_id = Column(Integer, nullable=True) type = Column(String(16, convert_unicode=True), nullable=False) sort_order = Column(Integer, default=0) settings = Column(JSON, default={}, nullable=True) diff --git a/cli/app/sql/versions/202103201916_remove_foreign_key_constraint_from_.py b/cli/app/sql/versions/202103201916_remove_foreign_key_constraint_from_.py new file mode 100644 index 0000000..ed19feb --- /dev/null +++ b/cli/app/sql/versions/202103201916_remove_foreign_key_constraint_from_.py @@ -0,0 +1,29 @@ +"""remove foreign key constraint from target_page_id + +Revision ID: 9b687880918d +Revises: 3f7df6bf63b8 +Create Date: 2021-03-20 19:16:21.582373 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utc + + +# revision identifiers, used by Alembic. +revision = '9b687880918d' +down_revision = '3f7df6bf63b8' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint('tile_ibfk_3', 'tile', type_='foreignkey') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_foreign_key('tile_ibfk_3', 'tile', 'page', ['target_page_id'], ['id']) + # ### end Alembic commands ### diff --git a/frontend/app/types.js b/frontend/app/types.js index bcd8053..f0f1e27 100644 --- a/frontend/app/types.js +++ b/frontend/app/types.js @@ -15,7 +15,7 @@ export const page = crud_type('page', [ 'update_page_tile', 'set_tile_sort_order', 'update_tile_sort_order', 'show_tile_list', 'hide_tile_list', 'toggle_tile_list', - 'toggle_popups', + 'toggle_popups', 'load_popups', 'toggle_sidebar_side', ]) diff --git a/frontend/app/views/page/components/page.editor.js b/frontend/app/views/page/components/page.editor.js index 2f14ffb..03190e3 100644 --- a/frontend/app/views/page/components/page.editor.js +++ b/frontend/app/views/page/components/page.editor.js @@ -174,6 +174,8 @@ class PageEditor extends Component { return (
{res.tiles && res.tiles.map(tile => { + console.log(tile.type, tile.settings.is_popup) + if (!this.props.page.editor.showingPopups && tile.settings.is_popup) return if (temporaryTile && temporaryTile.id === tile.id) { tile = temporaryTile } diff --git a/frontend/app/views/page/page.actions.js b/frontend/app/views/page/page.actions.js index c584848..0ae38e0 100644 --- a/frontend/app/views/page/page.actions.js +++ b/frontend/app/views/page/page.actions.js @@ -52,6 +52,20 @@ export const toggleTileList = () => dispatch => { // Popups +export const loadPopups = (page, popups) => dispatch => { + const state = store.getState() + page = page || state.page.show.res + popups = popups || state.page.editor.popups + popups = page.tiles.reduce((acc, tile) => { + const { is_popup, popup_group } = tile.settings + if (is_popup) { + acc[popup_group] = acc[popup_group] || false + } + return acc + }, { ...popups }) + console.log(popups) + dispatch({ type: types.page.load_popups, popups }) +} export const togglePopups = () => dispatch => { dispatch({ type: types.page.toggle_popups }) } diff --git a/frontend/app/views/page/page.container.js b/frontend/app/views/page/page.container.js index decdf79..0ad9806 100644 --- a/frontend/app/views/page/page.container.js +++ b/frontend/app/views/page/page.container.js @@ -44,6 +44,7 @@ class PageContainer extends Component { this.props.pageActions.showGraphAndPageIfUnloaded(this.props.match.params) .then(data => { actions.site.setSiteTitle(data.res.title) + this.props.pageActions.loadPopups(data.res, {}) if (!data.res.tiles.length) { this.props.pageActions.showAddTileForm() } else { diff --git a/frontend/app/views/page/page.reducer.js b/frontend/app/views/page/page.reducer.js index b0c4553..a1f281a 100644 --- a/frontend/app/views/page/page.reducer.js +++ b/frontend/app/views/page/page.reducer.js @@ -11,6 +11,7 @@ const initialState = crudState('page', { tileList: false, showingPopups: true, sidebarOnRight: true, + popups: {}, }, options: { } @@ -202,7 +203,16 @@ export default function pageReducer(state = initialState, action) { ...state, editor: { ...state.editor, - togglePopups: !state.editor.togglePopups, + showingPopups: !state.editor.showingPopups, + } + } + + case types.page.load_popups: + return { + ...state, + editor: { + ...state.editor, + popups: action.popups, } } diff --git a/frontend/app/views/tile/components/tile.form.js b/frontend/app/views/tile/components/tile.form.js index 728bc05..b33f7b8 100644 --- a/frontend/app/views/tile/components/tile.form.js +++ b/frontend/app/views/tile/components/tile.form.js @@ -76,6 +76,12 @@ const PAGE_LIST_TOP_OPTIONS = [ { name: -99, label: '──────────', disabled: true }, ] +const NO_POPUP = 0 +const POPUP_LIST_TOP_OPTIONS = [ + { name: NO_POPUP, label: 'Select a popup group' }, + { name: -99, label: '──────────', disabled: true }, +] + // target_page_id = Column(Integer, ForeignKey('page.id'), nullable=True) // https://s3.amazonaws.com/i.asdf.us/im/1c/gradient_gold1-SpringGreen1_1321159749.jpg @@ -181,6 +187,7 @@ class TileForm extends Component { errorFields: new Set([]), modified: false, pageList: [], + popupList: [], } constructor(props){ @@ -211,7 +218,11 @@ class TileForm extends Component { ...PAGE_LIST_TOP_OPTIONS, ...linkPages.map(page => ({ name: page.id, label: page.path })) ] - this.setState({ pageList }) + let popupList = [ + ...POPUP_LIST_TOP_OPTIONS, + ...Object.keys(page.editor.popups).map(popup_group => ({ name: popup_group, label: popup_group })) + ] + this.setState({ pageList, popupList }) if (isNew) { const newTile = newImage({ id: "new", @@ -760,7 +771,7 @@ class TileForm extends Component { renderHyperlinkForm() { const { temporaryTile } = this.props - const { pageList } = this.state + const { pageList, popupList } = this.state const isExternalLink = temporaryTile.target_page_id === EXTERNAL_LINK const isPopupLink = ( temporaryTile.target_page_id === OPEN_POPUP_LINK || @@ -785,8 +796,8 @@ class TileForm extends Component { onChange={this.handleSettingsSelect} />
-
- {isExternalLink && + {isExternalLink && ( +
- } -
+
+ )} + {(temporaryTile.target_page_id === OPEN_POPUP_LINK || temporaryTile.target_page_id === CLOSE_POPUP_LINK) && ( +
+